1.数据结构定义
1.1Node节点定义:保存key和vaue值,并且保存指针
Key value
forwards(保存每个节点指向下一个节点的指针数组,是数组的原因:每个节点有不同的层数,每一层都有一个指针)
Node<K, V> **forward;//Node指针数组
this->forward = new Node<K, V>*[level+1];//层级为0-level
memset(this->forward, 0, sizeof(Node<K, V>*)*(level+1));//对于数组进行初始化
1.2nodelist定义:
_max_level(最大的层数), _skip_list_level(此跳表层数), _element_count(跳表包含元素个数), header(跳表头节点,不包含数据), _file_writer, file_reader
2.函数操作
跳表操作:增删改查
2.1增加元素节点:找到比当前元素小的最大节点,在该元素节点后插入新的节点
实现方式:
Node<K, V> *update[_max_level + 1]:保存遍历到的符合条件的每一层的指针(即寻找插入位置的时候是从最高层数开始,要保存在每一层找到的那个节点,插入的时候方便将新的节点直接插入保存下来的指针后面)
对于新插入节点的level值,这里采用的是随机生成的方式,要注意的是当随机生成的level值比当前跳表的_skip_list_level大的时候,要对该值进行更新
2.2数据落盘、数据加载函数
数据落盘:将跳表数据保存到磁盘上
这里只遍历forward[0]即可,即只保存节点数据信息,不保存层信息。
数据写入时,在节点的key和value之间加上冒号进行分隔
数据加载:将磁盘数据加载到内存的跳表结构上
3.相关知识点
3.1落盘 刷盘
落盘:就是将数据写入到磁盘(存储介质);
刷盘:并不是每次接收到数据后就将数据写入到磁盘,而是会先写入缓冲区,将缓冲区的数据写入到磁盘的过程,称为刷盘。
3.2遇到的问题:
使用模板函数或模板类时要将声明与定义都在.h文件中实现。
3.3 memset
strcpy函数的原型:
char* strcpy(char* dest, const char* src);
memcpy函数的原型:
void *memcpy( void *dest, const void *src, size_t count );
memset函数的原型:
memset(void *s, int ch,size_t n);
3.3.1strcpy,memcpy区别:
a.复制内容不同,strcpy只能复制字符串,而memcpy可以复制任一内容,比如整形、结构体等。所以在复制字符串时会用strcpy(因为效率原因),而复制其他类型数据一般会用memcpy。
b.从参数可以看出复制方法也不尽相同。strcpy不需要指定特定长度,遇到“\0”才会结束,所以使用不当容易造成溢出。memcpy则是根据第三个参数决定复制长度。
3.3.2 memset
一定要注意,memset是按照字节对空间进行初始化的,也就是说,函数里面的第二个参数的那个初值(一般为0)是按照一个一个字节往第一个参数所指区域赋值的,所以,对于单字节数据类型(char)可以初始化为任意支持的值,但是对于非多字节数据类型只能初始化为0,而不能初始化成别的初值。