05 关于 intset

Posted 蓝风9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了05 关于 intset相关的知识,希望对你有一定的参考价值。

前言

关于 redis 的数据结构 intset 

相关介绍主要围绕着如下测试用例, 来看看 intset 的存储, 以及 相关的 api 

本文的 intset 相关代码 拷贝自 redis-6.2.0  

代码来自于 https://redis.io/ 

 

 

测试用例

//
// Created by Jerry.X.He on 2021/2/25.
//

#include <iostream>
#include "../libs/intset.h"

using namespace std;

int main(int argc, char **argv) {

    intset *set = intsetNew();

    uint8_t succeed = 0;
    int removeSucceed = 0;
    int64_t value = 0;

    for (int64_t i = 11; i <= 20; i++) {
        set = intsetAdd(set, (int64_t) i, &succeed);
    }

    // intsetAdd
    set = intsetAdd(set, 1, &succeed);
    set = intsetAdd(set, 1, &succeed);

    // intsetRemove
    intsetRemove(set, 12, &removeSucceed);

    // intsetFind
    int findResult = intsetFind(set, 15);

    // intsetRandom
    int randomResult = intsetRandom(set);

    // intsetGet
    intsetGet(set, 2, &value);

    // intsetLen
    int len = intsetLen(set);

    // intsetBlobLen
    int setBytes = intsetBlobLen(set);

    int x = 0;

}

 

 

数据结构 

encoding 表示 contents 中的数据以 几字节 来编码, len 表示 元素的数量 

contents 来存储具体的元素数据 

 

encoding 有如下几种 

 

 

intsetNew

创建一个 intset, 初始化 encoding 为 int_16, len 为 0

 

 

intsetAdd

判断需要添加的 val 的编码, 如果 所需编码更大, 切换 set 的编码类型, 并添加元素
    更新 set.encoding 为新加入的 val 的编码
    resize set, 更新集合空间, 将 set 中的所有元素, 向后移动
    在这种情况下 val 是最大的元素, 或者最小的元素, 加入表头 或者 表尾, 更新集合长度
否则 查询是否有 val 对应的元素, 如果有 直接返回
    resize 更新集合空间, 将大于 val 之后的元素移动到之后, 插入 val, 新增 len 的长度

 

我们来 inspect 一下 is, 在我们这里添加元素 1 之前, intset 里面已经有了 11 - 20, 10 个元素 

encoding 为 0x02, 表示 INT16, 约束了后面的数据 每一个元素占用 2 字节 

len 为 0x0b 等于 11 

后面以两字节为单位, 分别是接下来的 11 个元素 

1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 

(lldb) x 0x7fedd9d001f0
0x7fedd9d001f0: 02 00 00 00 0b 00 00 00 01 00 0b 00 0c 00 0d 00  ................
0x7fedd9d00200: 0e 00 0f 00 10 00 11 00 12 00 13 00 14 00 00 b0  ...............�

 

 

intsetRemove 

判断需要添加的 val 的编码, 如果 所需编码更大, 表示当前 set 肯定没有改元素
查找 val 所在的位置, 如果存在, 则将 val 之后的元素向前移动一个单元, resize 更新集合空间, 更新 len 的长度

 

我们来 inspect 一下 is, 在我们这里添加元素 1 之前, intset 里面已经有了 11 - 20, 10 个元素 

encoding 为 0x02, 表示 INT16, 约束了后面的数据 每一个元素占用 2 字节 

len 为 0x0a 等于 10 

后面以两字节为单位, 分别是接下来的 11 个元素 

1, 11, 13, 14, 15, 16, 17, 18, 19, 20 

(lldb) x 0x7fedd9d001f0
0x7fedd9d001f0: 02 00 00 00 0a 00 00 00 01 00 0b 00 0d 00 0e 00  ................
0x7fedd9d00200: 0f 00 10 00 11 00 12 00 13 00 14 00 14 00 00 b0  ...............�

 

 

intsetFind

判断需要添加的 val 的编码, 如果 所需编码更大, 表示当前 set 肯定没有改元素
如果给定的集合为空, 或者 val 大于 set 的最大的元素, 或者 val 小于 set 的最小的元素, 直接返回
二分查找 val 所在的位置, pos 更新为该位置
如果不存在, pos 更新为 比val小的第一个元素的位置 

返回 value 是否存在

 

 

intsetRandom

随机计算一个索引, 然后获取索引对应的元素
set->contents + 索引直接获取 元素

 

 

intsetGet

set->contents + 索引直接获取 元素

 

 

intsetLen

获取 set 的长度, 直接从元数据获取

 

 

intsetBlobLen 

计算方式 sizeof(intset) + 元素数量 + sizeof(元素)

 

 

 

 

以上是关于05 关于 intset的主要内容,如果未能解决你的问题,请参考以下文章

使用 NavController 从片段导航到另一个片段

关于代码片段的时间复杂度

关于片段生命周期

关于js----------------分享前端开发常用代码片段

在片段中调用 getActivity() 以使其不返回 null 的最佳做法是啥? [复制]

sql: sp_cursorexecute 执行错误