数据结构

image.png

  1. typedef struct intset {
  2. uint32_t encoding;
  3. uint32_t length;
  4. int8_t contents[];//一个字节
  5. } intset;
  6. int main() {
  7. struct intset *set = malloc(sizeof(struct intset));
  8. set->encoding = 1;
  9. set->length = 2;
  10. set->contents[0] = 1;
  11. set->contents[1] = 22;
  12. printf("内存地址0:%p\n", *&set);
  13. printf("内存地址1:%p\n", &set->encoding);
  14. printf("内存地址2:%p\n", &set->length);
  15. printf("内存地址3:%p\n", &set->contents[0]);
  16. printf("内存地址4:%p\n", &set->contents[1]);
  17. free(set);
  18. }
  19. //output如下
  20. //内存地址0:0x7fd8b0c05a20
  21. //内存地址1:0x7fd8b0c05a20
  22. //内存地址2:0x7fd8b0c05a24
  23. //内存地址3:0x7fd8b0c05a28
  24. //内存地址4:0x7fd8b0c05a29

在Redis的整数集合中, contents 数组的大小取决于 encoding的编码

  1. #define INTSET_ENC_INT16 (sizeof(int16_t))
  2. #define INTSET_ENC_INT32 (sizeof(int32_t))
  3. #define INTSET_ENC_INT64 (sizeof(int64_t))
  4. //这里还涉及到字节顺

整数集合操作

创建

  • 创建一个结构体(malloc),初始化 encoding length

    1. intset *intsetNew(void) {
    2. intset *is = zmalloc(sizeof(intset));
    3. is->encoding = intrev32ifbe(INTSET_ENC_INT16);
    4. is->length = 0;
    5. return is;
    6. }

    插入

    image.png

    查找(数据是否存在)

  • intset没有数据,返回

  • value大于最大 || value小于最小 , 返回
  • 二分查找找到value (二分查找),算法无处不在

    • 数据存在,返回1
    • 数据不存在反问2

      1. static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) {
      2. //数组长度
      3. int min = 0, max = intrev32ifbe(is->length)-1, mid = -1;
      4. int64_t cur = -1;
      5. //整数集合没有数据
      6. if (intrev32ifbe(is->length) == 0) {
      7. if (pos) *pos = 0;
      8. return 0;
      9. } else {
      10. //value大于最大 || value小于最小 , 返回
      11. if (value > _intsetGet(is,max)) {
      12. if (pos) *pos = intrev32ifbe(is->length);
      13. return 0;
      14. } else if (value < _intsetGet(is,0)) {
      15. if (pos) *pos = 0;
      16. return 0;
      17. }
      18. }
      19. //二分
      20. while(max >= min) {
      21. mid = ((unsigned int)min + (unsigned int)max) >> 1;
      22. cur = _intsetGet(is,mid);
      23. if (value > cur) {
      24. min = mid+1;
      25. } else if (value < cur) {
      26. max = mid-1;
      27. } else {
      28. break;
      29. }
      30. }
      31. //是否找到数据
      32. if (value == cur) {
      33. if (pos) *pos = mid;
      34. return 1;
      35. } else {
      36. if (pos) *pos = min;
      37. return 0;
      38. }
      39. }

      删除

      image.png

      字节序

      大端字节序和小端字节序
      https://blog.erratasec.com/2016/11/how-to-teach-endian.html#.YjKhpxBByAl
      encoding如何进行判定

      1. /* Return the required encoding for the provided value. */
      2. static uint8_t _intsetValueEncoding(int64_t v) {
      3. //超过32位最大的和小于32位最小的,使用64位
      4. if (v < INT32_MIN || v > INT32_MAX)
      5. return INTSET_ENC_INT64;
      6. else if (v < INT16_MIN || v > INT16_MAX)
      7. //超过16位最大的和小于16位最小的,使用32位
      8. return INTSET_ENC_INT32;
      9. else
      10. //剩下的全部使用16位
      11. return INTSET_ENC_INT16;
      12. }