数据结构
SDS
定义
struct sdshdr{
int len;
int free;
char buf[];
}
SDS与C字符串的区别
(1)常数复杂度获取字符串长度。C字符串需要遍历,以'\0'为结尾。
(2)杜绝缓冲区溢出。C字符串分配的内存可能不够,strcat操作时可能溢出。而SDS可以动态地扩展空间。
(3)减少修改字符串带来的内存重分配次数。C字符串在append或trim时,总要对这个C字符串进行一次内存重分配操作。而SDS采用空间预分配和惰性空间释放保留一部分空间,以免引起频繁重分配。
(4)二进制安全。C字符串会因为'\0'意外终止。
LinkedList
定义
Dict
定义
//哈希表
typedef struct dictht {
dictEntry **table;
unsigned long size;
unsigned long sizemark;
unsigned long used;
} dictht;
//哈希表节点
typedef struct dictEntry {
void *key;
union{
void *val;
...
} v;
struct dictEntry *next;
} dictEntry;
字典是一种保存键值对的抽象数据结构。
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
int rehashidx;
} dict;
哈希算法
解决键冲突
使用链接地址法来解决键冲突。
rehash
(1)为字典的ht[1]哈希表分配空间。
(2)将保存在ht[0]中的所有键值对rehash到ht[1]上(重新计算哈希值和索引值)。要注意到ht[0]和ht[1]里的sizemark哈希掩码是不一样的。
(3)释放ht[0],将ht[1]设置为ht[0],并在ht[1]上新建一个空白哈希表。
扩展或收缩的条件
渐进式rehash
哈希表渐进式rehash的详细步骤:
将rehash键值对的计算量均摊到每个增删改查操作中,避免了集中rehash带来的工作量。
SkipList
定义
跳表是一种有序数据结构,通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问的目的。平均O(logN),最坏O(N)。
我们知道链表是无法二分查找的,跳表就是加了很多指向其他节点的指针后,在链表上实现二分查找。
一个跳跃表节点结构如下
//跳跃表节点
typedef struct zskiplistNode {
struct zskiplistLevel {
struct zskiplistNode *forward; //前进指针
unsigned int span; //跨度
} level[];
struct zskiplistNode *backward; //后退指针
double score; //分值,节点按各自所保存的分值从小到大排列
robj *obj; // 成员对象
} zskiplistNode;
//跳跃表
typedef struct zskiplist {
structz skiplistNode *header, *tail; //表头节点和表尾节点
unsigned long length; //表中节点的数量
int level; //层数最大节点的层数
} zskiplist;
跳表和B+树的区别与选择:www.51cto.com/article/706…