ÕûÊý¼¯ºÏ¼ò½é
ÕûÊý¼¯ºÏintsetÓÃÓÚÓÐÐò¡¢ÎÞÖØ¸´µØ±£´æ¶à¸öÕûÊýÖµ£¬¸ù¾Ý¼¯ºÏÖÐÔªËØµÄÖµ×Ô¶¯Ñ¡ÔñʹÓÃÕûÊýÀàÐÍÀ´±£´æÔªËØ£¬ÀýÈ磺Èç¹ûintsetÖоø¶ÔÖµ×î´óµÄÕûÊý¿ÉÒÔÓÃint32_tÀ´±£´æ£¬ÄÇôÕû¸öintsetÖÐËùÓÐÔªËØ¶¼Ê¹ÓÃint32_tÀ´±£´æ¡£
Èç¹ûµ±Ç°intsetËùʹÓõÄÀàÐͲ»Äܱ£´æÒ»¸ö¼´½«¼ÓÈëµ½¸ÃintsetµÄÐÂÔªËØÊ±ºò£¬ÐèÒª¶Ôintset½øÐÐÉý¼¶£¬±ÈÈçÐÂÔªËØµÄÀàÐÍÊÇint64_t£¬¶øµ±Ç°intsetµÄÀàÐÍÊÇint32_t£¬ÄÇôÉý¼¶¾ÍÊÇÏȽ«intsetÖÐËùÓÐÔªËØÓÉint32_tת»»Îªint64_t£¬È»ºóÔÙ²åÈëÐÂÔªËØ¡£
¶ÔÓÚint8_t,int32_t,int64_tÎÒ¸öÈ˵ÄÀí½â¾ÍÓ¦¸Ã·Ö±ð¶ÔÓ¦char,int,long long£¬Ê¹ÓÃint8_t,int32_t,int64_tÓ¦¸ÃÊÇΪÁËÇø·Öƽ̨µÄ²îÒì°É£¬¾ßÌåµÄ¿ÉÒԲ鿴stdint.hÎļþ¡£
ÕûÊý¼¯ºÏµÄÊý¾Ý½á¹¹
typedef struct intset {
uint32_t encoding; //ËùʹÓÃÀàÐ͵ij¤¶È£¬4\8\16
uint32_t length; //ÔªËØ¸öÊý
int8_t contents[]; //±£´æÔªËصÄÊý×é
} intset;
encodingµÄÖµÊÇÏÂÃæÈý¸ö³£Á¿ÖеÄÒ»¸ö£º
#define INTSET_ENC_INT16 (sizeof(int16_t))
#define INTSET_ENC_INT32 (sizeof(int32_t))
#define INTSET_ENC_INT64 (sizeof(int64_t))
contentsÊý×éÓÃÀ´Êµ¼Ê±£´æÊý¾Ý£¬Êý×éÖÐÔªËØµÄÌØÐÔ£ºÎÞÖØ¸´ÔªËØ£»ÔªËØÔÚÊý×éÖеÝÔöÅÅÁС£
ÕûÊý¼¯ºÏÏà¹ØAPI½éÉÜ
| º¯ÊýÃû³Æ |
×÷ÓÃ |
¸´ÔÓ¶È |
| _intsetValueEncoding |
»ñÈ¡¸ø¶¨ÕûÊýµÄ±àÂëÀàÐÍ |
O(1) |
| _intsetGet |
¸ù¾ÝË÷Òý»ñÈ¡ÕûÊýÖµ |
O(1) |
| _intsetSet |
¸ù¾ÝË÷ÒýÉèÖøø¶¨ÕûÊýÖµ |
O(1) |
| intsetNew |
н¨intset |
O(1) |
| intsetResize |
Ϊ¸ø¶¨µÄintsetÖØÐ·ÖÅäÄÚ´æ |
O(1) |
| intsetSearch |
²éÕÒ¸ø¶¨µÄÕûÊýÊÇ·ñÔÚintsetÖÐ |
O(logN) |
| intsetUpgradeAndAdd |
ÏÈÉý¼¶intsetÈ»ºó²åÈëÔªËØ |
O(N) |
| intsetAdd |
Ö±½ÓÌí¼ÓÔªËØ |
O(N) |
| intsetMoveTail |
½«intsetÖÐÔªËØÆ«ÒÆ |
O(N) |
| intsetRemove |
ɾ³ýÔªËØ |
O(N) |
| intsetRandom |
Ëæ»ú·µ»ØÒ»¸öintsetÖÐÔªËØ |
O(1) |
| intsetLen |
intsetÖÐÔªËØµÄ¸öÊý |
O(1) |
| intsetBlobLen |
intsetËùÕ¼µÄ×Ö½ÚÊý |
O(1) |
ÖØÒªAPIÔ´ÂëµÄ¼òµ¥½âÎö
intsetAdd
//Ìí¼ÓÒ»¸öÕûÊý
intset *intsetAdd(intset *is, int64_t value, uint8_t *success) {
uint8_t valenc = _intsetValueEncoding(value); //µÃµ½ÀàÐ͵ij¤¶È
uint32_t pos;
if (success) *success = 1;
/* Upgrade encoding if necessary. If we need to upgrade, we know that
* this value should be either appended (if > 0) or prepended (if < 0),
* because it lies outside the range of existing values. */
//ÐèÒªÉý¼¶£¬ÄÇô½øÐÐÉý¼¶²¢²åÈëÐÂÖµ
if (valenc > intrev32ifbe(is->encoding)) {
/* This always succeeds, so we don't need to curry *success. */
return intsetUpgradeAndAdd(is,value);
} else {//·ñÔò
/* Abort if the value is already present in the set.
* This call will populate "pos" with the right position to insert
* the value when it cannot be found. */
//Èç¹û¸ÃÖµÔÚ¼¯ºÏÖÐÒѾ´æÔÚ£¬ÄÇôֱ½Ó·µ»Ø
if (intsetSearch(is,value,&pos)) {
if (success) *success = 0;
return is;
}
is = intsetResize(is,intrev32ifbe(is->length)+1);
//½«´ÓposλÖúóÃæµÄֵȫ²¿ÏòºóÆ«ÒÆÒ»¸öλÖã¬ÎªÐÂÔªËØ¿Õ³öλÖÃ
if (pos < intrev32ifbe(is->length)) intsetMoveTail(is,pos,pos+1);
}
_intsetSet(is,pos,value);//Ìí¼ÓÐÂÔªËØ
is->length = intrev32ifbe(intrev32ifbe(is->length)+1);
return is;
}
intsetAddº¯ÊýÌí¼ÓÒ»¸öÔªËØvalueʱ£¬Ê×Ïȸù¾ÝvalueµÄ×Ö½ÚÊýÓ뵱ǰintsetµÄencoding½øÐбȽϣ¬·ÖÎöintsetÊÇ·ñÐèÒªÉý¼¶£¬ÈôÐèÒªÉý¼¶Ôòµ÷ÓÃintsetUpdateAndAddº¯Êý´¦Àí£¬·ñÔòÈç¹ûvalueÒÑ´æÔÚintsetÖÐÖ±½Ópass£¬²»´æÔÚ£¬ÄÇôÏÈresize£¬½Ó׎«²åÈëλÖÃÖ®ºóµÄËùÓÐÔªËØÏòºóÆ«ÒÆ£¬Ìí¼Óvalue¡£
intsetMoveTail
/**ʹÓÃmemmove¶Ô¼¯ºÏ½øÐÐÏòºóÆ«ÒÆ,ϱê´Ó0¿ªÊ¼£¬²¢ÇÒÒѾResize
Àý:ǰ | 1 | 2 | 3 | 4 | 5 | 6 | | |
from = 1, to = 3
length = 6
src = | 2 | 3 | 4 | 5 | 6 |
dst = | 4 | 5 | 6 | | |
bytes = 5 * sizeof(...)
ºó | 1 | 2 | 3 | 2 | 3 | 4 | 5 | 6 |
Æ«ÒÆÖ®Ç°¿Ï¶¨ÐèÒªÓÃintsetResizeº¯Êý£¬½øÐÐÀ©ÈÝ£¬Ôö¼ÓÁ½¸öÈÝÁ¿
Èç¹û²»Àí½âǰºóµÄ±ä»¯£¬½¨Òé²é¿´memmoveÔ´Â룬ÕâÀïÐèÒª¿¼Âǵ½Äڴ渲¸ÇµÄÎÊÌâ
Ò²¾ÍÊÇΪʲô±ØÐëʹÓÃmemmove¶ø²»ÄÜʹÓÃmemcpyµÄÔÒò
*/
static void intsetMoveTail(intset *is, uint32_t from, uint32_t to) {
void *src, *dst;
uint32_t bytes = intrev32ifbe(is->length)-from;
uint32_t encoding = intrev32ifbe(is->encoding);
if (encoding == INTSET_ENC_INT64) {
src = (int64_t*)is->contents+from;
dst = (int64_t*)is->contents+to;
bytes *= sizeof(int64_t);
} else if (encoding == INTSET_ENC_INT32) {
src = (int32_t*)is->contents+from;
dst = (int32_t*)is->contents+to;
bytes *= sizeof(int32_t);
} else {
src = (int16_t*)is->contents+from;
dst = (int16_t*)is->conten