文章目录
- 概述
- IntSet升级
- 简易源码
- 总结
欢迎来到 请回答1024 的博客 |
🍎🍎🍎欢迎来到 请回答1024的博客
关于博主: 我是 请回答1024,一个追求数学与计算的边界、时间与空间的平衡,0与1的延伸的后端开发者。
博客特色: 在我的博客中,开设了如下专栏(点击可以进入专栏奥~): Java、MySQL、Redis、Spring、SpringBoot、SpringCloud、RabbitMQ、微服务、分布式 等相关技术专栏。期待与您一起,探索编程世界中的发现和创新之旅。
🌈我的主页 : https://reply1024.blog.csdn.net
敬请期待定期更新、见解和教程!让我们一起踏上这段编码冒险之旅!
数学与计算的边界 时间与空间的平衡 0与1的延伸 |
概述
IntSet
是Redis
中set集合的一种实现方式,基于 整数数组 来实现,并且具备长度可变、有序等特征。
结构如下:
// intset 结构体定义
typedef struct intset {
uint32_t encoding; // 编码方式,用于表示存储的整数类型
uint32_t length; // intset 中包含的元素个数
int8_t contents[]; // 存储整数的数组
} intset;
其中的 encoding 包含三种模式,表示存储的整数大小不同:
为了方便查找,Redis 会将 intset 中所有的整数按照 升序 依次保存在contents数组中,结构如图:
IntSet升级
假如现在,数组中每个数字都在 int16_t 的范围内,因此采用的编码方式是 INTSET_ENC_INT16,每部分占用的字节大小为:
encoding
:4字节
length
:4字节
contents
:2字节 * 3 = 6字节
我们向该其中添加一个数字:50000,这个数字超出了 int16_t 的范围,intset
会自动 升级 编码方式到合适的大小。
以当前案例来说流程如下:
- 升级编码为 INTSET_ENC_INT32, 每个整数占4字节,并按照新的编码方式及元素个数扩容数组
- 倒序 依次将数组中的元素拷贝到扩容后的正确位置
- 将待添加的元素放入数组末尾
- 最后,将 inset 的 encoding 属性改为 INTSET_ENC_INT32 ,将 length 属性改为4
简易源码
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
// intset 结构体定义
typedef struct intset {
uint32_t encoding; // 编码方式,用于表示存储的整数类型
uint32_t length; // intset 中包含的元素个数
int8_t contents[]; // 存储整数的数组
} intset;
// 创建一个新的 intset
intset *intset_new() {
intset *is = malloc(sizeof(intset));
if (!is) return NULL;
is->encoding = 0; // 初始编码方式为 0
is->length = 0;
return is;
}
// 添加整数到 intset
intset *intset_add(intset *is, int64_t value) {
// 添加元素的逻辑实现省略
return is;
}
// 检查整数是否存在于 intset
int intset_contains(const intset *is, int64_t value) {
// 检查元素是否存在的逻辑实现省略
return 0;
}
// 删除整数从 intset
intset *intset_remove(intset *is, int64_t value) {
// 删除元素的逻辑实现省略
return is;
}
// 打印 intset 中的元素
void intset_print(const intset *is) {
printf("Intset Length: %d\n", is->length);
printf("Intset Elements: ");
for (int i = 0; i < is->length; ++i) {
printf("%lld ", (long long)is->contents[i]);
}
printf("\n");
}
int main() {
intset *is = intset_new();
if (!is) {
printf("Error: Unable to create intset.\n");
return 1;
}
is = intset_add(is, 5);
is = intset_add(is, 10);
is = intset_add(is, 15);
intset_print(is);
// 检查元素是否存在
if (intset_contains(is, 10)) {
printf("Element 10 exists in the intset.\n");
} else {
printf("Element 10 does not exist in the intset.\n");
}
is = intset_remove(is, 10);
intset_print(is);
free(is);
return 0;
}
总结
Intset可以看做是特殊的整数数组,具备一些特点:
- Redis会确保Intset中的元素唯一、有序
- 具备类型升级机制,可以节省内存空间
- 底层采用二分查找方式来查询