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的主要内容,如果未能解决你的问题,请参考以下文章
关于js----------------分享前端开发常用代码片段