数据结构
typedef struct intset {
uint32_t encoding;
uint32_t length;
int8_t contents[];//一个字节
} intset;
int main() {
struct intset *set = malloc(sizeof(struct intset));
set->encoding = 1;
set->length = 2;
set->contents[0] = 1;
set->contents[1] = 22;
printf("内存地址0:%p\n", *&set);
printf("内存地址1:%p\n", &set->encoding);
printf("内存地址2:%p\n", &set->length);
printf("内存地址3:%p\n", &set->contents[0]);
printf("内存地址4:%p\n", &set->contents[1]);
free(set);
}
//output如下
//内存地址0:0x7fd8b0c05a20
//内存地址1:0x7fd8b0c05a20
//内存地址2:0x7fd8b0c05a24
//内存地址3:0x7fd8b0c05a28
//内存地址4:0x7fd8b0c05a29
在Redis的整数集合中, contents
数组的大小取决于 encoding的编码
#define INTSET_ENC_INT16 (sizeof(int16_t))
#define INTSET_ENC_INT32 (sizeof(int32_t))
#define INTSET_ENC_INT64 (sizeof(int64_t))
//这里还涉及到字节顺
整数集合操作
创建
创建一个结构体(malloc),初始化
encoding
length
intset *intsetNew(void) {
intset *is = zmalloc(sizeof(intset));
is->encoding = intrev32ifbe(INTSET_ENC_INT16);
is->length = 0;
return is;
}
插入
查找(数据是否存在)
intset没有数据,返回
- value大于最大 || value小于最小 , 返回
二分查找找到value (二分查找),算法无处不在
- 数据存在,返回1
数据不存在反问2
static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) {
//数组长度
int min = 0, max = intrev32ifbe(is->length)-1, mid = -1;
int64_t cur = -1;
//整数集合没有数据
if (intrev32ifbe(is->length) == 0) {
if (pos) *pos = 0;
return 0;
} else {
//value大于最大 || value小于最小 , 返回
if (value > _intsetGet(is,max)) {
if (pos) *pos = intrev32ifbe(is->length);
return 0;
} else if (value < _intsetGet(is,0)) {
if (pos) *pos = 0;
return 0;
}
}
//二分
while(max >= min) {
mid = ((unsigned int)min + (unsigned int)max) >> 1;
cur = _intsetGet(is,mid);
if (value > cur) {
min = mid+1;
} else if (value < cur) {
max = mid-1;
} else {
break;
}
}
//是否找到数据
if (value == cur) {
if (pos) *pos = mid;
return 1;
} else {
if (pos) *pos = min;
return 0;
}
}
删除
字节序
大端字节序和小端字节序
https://blog.erratasec.com/2016/11/how-to-teach-endian.html#.YjKhpxBByAl
encoding如何进行判定/* Return the required encoding for the provided value. */
static uint8_t _intsetValueEncoding(int64_t v) {
//超过32位最大的和小于32位最小的,使用64位
if (v < INT32_MIN || v > INT32_MAX)
return INTSET_ENC_INT64;
else if (v < INT16_MIN || v > INT16_MAX)
//超过16位最大的和小于16位最小的,使用32位
return INTSET_ENC_INT32;
else
//剩下的全部使用16位
return INTSET_ENC_INT16;
}