跳表也是key-value的形式存储,跳表(skip list) 对标的是平衡二叉树(AVL Tree),是一种插入/删除/搜索都是O(logn)的数据结构。在一些热门的项目里用来替代平衡二叉树,如redis,leveldb等。
我的理解:跳表其实就是建立多层索引(多层链表)。
显然:每列的key值都是一样的。此外,每个结点到底有多少层是由概率来计算的。
上图跳表中的数字是key值,可见,如果要查找key值为12的结点,从head结点开始,5跳就可以找到了。具体的跳跃规则写在代码中了。
每个结点都有一个key、一个value以及一个指针数组。
template<typename T>
class SkipNode {
public:
int key;
T value;
vector<SkipNode*> next;
SkipNode(int key, T value, int level);
};
//constructor
template<typename T> SkipNode<T>::SkipNode(int key, T value, int level) : key(key), value(value)
{
for (int i = 0; i < level; i++)
{
next.push_back(nullptr);
}
}
template<class T>
class SkipList {
public:
//头结点
SkipNode<T>* head;
//列表最大层数
int maxLevel;
//整型的最小值和最大值
static const int minInt = numeric_limits<int>::min();
static const int maxInt = numeric_limits<int>::max();
//constructor
SkipList(int maxLevel, T iniValue);
//destructor
~SkipList() {
delete head;
delete tail;
}
//随机层数方法
int randomLevel();
//插入,查找,删除操作
SkipNode<T>* insert(int key, T value);
SkipNode<T>* find(int key);
SkipNode<T>* deleteNode(int key);
private:
//尾结点
SkipNode<T>* tail;
//找到当前跳表或者node的最大层数
int nodeLevel(vector<SkipNode<T>*> p);
};
template<class T> SkipList<T>::SkipList(int maxLevel, T iniValue) :maxLevel(maxLevel)
{
//初始化头结点和尾结点的key值为整型最小值和最大值
head = new SkipNode<T>(minInt, iniValue, maxLevel);//头结点的key为minInt
tail = new SkipNode<T>(maxInt, iniValue, maxLevel);//尾结点的key为maxInt
//所有层数上的头结点指向尾结点
for (int i = 0; i < maxLevel; i++)
{
head->next[i] = tail;
}
}
template<class T> int SkipList<T>::randomLevel()
{
int random_level = 1;
int seed = time(NULL);
static default_random_engine e(seed);
static uniform_int_distribution<int> u(0, 1);
while (u(e) && random_level < maxLevel)
{
random_level++;
}
return random_level;
}
template<class T> int SkipList<T>::nodeLevel(vector<SkipNode<T>*> next)
{
return next.size();
}
/*查找:
由于列表有序,首先找到小于该结点的最近的结点,如果下一个结点等于目标结点,则返回该结点。
如果不是,则返回空*/
template<class T> SkipNode<T>* SkipList<T>::find(int key)//根据key值找
{
SkipNode<T>* tmp = head;
int current_level = nodeLevel(tmp->next);
for (int i = (current_level - 1); i >= 0; i--)//往下走
{
while (tmp->next[i] != nullptr && tmp->next[i]->key < key)
{
tmp = tmp->next[i];//往右走
}
}
tmp = tmp->next[0];//再往右走一步
if (tmp->key == key)
{
cout << "This key " << key << " has been found" << endl;
return tmp;
}
else
{
return nullptr;
}
}
/*插入:
1)首先用查找函数来判断该结点是否已经存在,如果存在,则更新该结点的值
2)获取新结点的随机层数
3)找到合适的插入位置
4)插入,并调整每层前后node的指针*/
template<class T> SkipNode<T>* SkipList<T>::insert(int key, T value)
{
int x_level = randomLevel();//获取新结点的随机层数
SkipNode<T>* new_node = nullptr;
SkipNode<T>* tmp = head;
new_node = find(key);
if (new_node) {
new_node->value = value;
cout << "This node " << key << " has already existed. And its value has been updated to " << value << endl;
return head;
}
cout << "key: " << key << ", randomLevel: " << x_level << endl;
new_node = new SkipNode<T>(key, value, x_level);
for (int i = (x_level - 1); i >= 0; i--)
{
while (tmp->next[i] != nullptr && tmp->next[i]->key < key)
{
tmp = tmp->next[i];
}
//此时tmp为第i层小于key的最近的结点,接下来完成连接即可
new_node->next[i] = tmp->next[i];
tmp->next[i] = new_node;
}
return head;
}
/*删除:
1) 用 find方法判断该结点是否存在. 如果不存在,则返回当前list, 并告知该结点不存在
2) 找到小于该结点的最近的结点
3) 更改该结点每层的前面的结点的指针*/
template<class T> SkipNode<T>* SkipList<T>::deleteNode(int key)
{
SkipNode<T>* node = find(key);
if (!node)
{
cout << "This deleting node" << key << "doesn't exist" << endl;
return head;
}
else
{
SkipNode<T>* tmp = head;
int x_level = node->next.size();
cout << "The deleting node " << key << "'s level is " << x_level << endl;
for (int i = (x_level - 1); i >= 0; i--)
{
while (tmp->next[i] != nullptr && tmp->next[i]->key < key)
{
tmp = tmp->next[i];
}
tmp->next[i] = tmp->next[i]->next[i];
cout << "This node " << key << " has been deleted from level " << i << endl;
}
return head;
}
}
#include
#include
#include
using namespace std;
template<typename T>
class SkipNode {
public:
int key;
T value;
vector<SkipNode*> next;
SkipNode(int key, T value, int level);
};
//constructor
template<typename T> SkipNode<T>::SkipNode(int key, T value, int level) : key(key), value(value)
{
for (int i = 0; i < level; i++)
{
next.push_back(nullptr);
}
}
template<class T>
class SkipList {
public:
//头结点
SkipNode<T>* head;
//列表最大层数
int maxLevel;
//整型的最小值和最大值
static const int minInt = numeric_limits<int>::min();//头结点的key为minInt
static const int maxInt = numeric_limits<int>::max();//尾结点的key为maxInt
//constructor
SkipList(int maxLevel, T iniValue);
//destructor
~SkipList() {
delete head;
delete tail;
}
//随机层数方法
int randomLevel();
//插入,查找,删除操作
SkipNode<T>* insert(int key, T value);
SkipNode<T>* find(int key);
SkipNode<T>* deleteNode(int key);
private:
//尾结点
SkipNode<T>* tail;
//找到当前跳表或者node的最大层数
int nodeLevel(vector<SkipNode<T>*> p);
};
//初始化
template<class T> SkipList<T>::SkipList(int maxLevel, T iniValue) :maxLevel(maxLevel)
{
//初始化头结点和尾结点的key值为整型最小值和最大值
head = new SkipNode<T>(minInt, iniValue, maxLevel);//头结点的key为minInt
tail = new SkipNode<T>(maxInt, iniValue, maxLevel);//尾结点的key为maxInt
//所有层数上的头结点指向尾结点
for (int i = 0; i < maxLevel; i++)
{
head->next[i] = tail;
}
}
template<class T> int SkipList<T>::randomLevel()
{
int random_level = 1;
int seed = time(NULL);
static default_random_engine e(seed);
static uniform_int_distribution<int> u(0, 1);
while (u(e) && random_level < maxLevel)
{
random_level++;
}
return random_level;
}
template<class T> int SkipList<T>::nodeLevel(vector<SkipNode<T>*> next)
{
return next.size();
}
/*查找:
由于列表有序,首先找到小于该结点的最近的结点,如果下一个结点等于目标结点,则返回该结点。
如果不是,则返回空*/
template<class T> SkipNode<T>* SkipList<T>::find(int key)//根据key值找
{
SkipNode<T>* tmp = head;
int current_level = nodeLevel(tmp->next);
for (int i = (current_level - 1); i >= 0; i--)//往下走
{
while (tmp->next[i] != nullptr && tmp->next[i]->key < key)
{
tmp = tmp->next[i];//往右走
}
}
tmp = tmp->next[0];//再往右走一步
if (tmp->key == key)
{
cout << "This key " << key << " has been found" << endl;
return tmp;
}
else
{
return nullptr;
}
}
/*插入:
1)首先用查找函数来判断该结点是否已经存在,如果存在,则更新该结点的值
2)获取新结点的随机层数
3)找到合适的插入位置
4)插入,并调整每层前后node的指针*/
template<class T> SkipNode<T>* SkipList<T>::insert(int key, T value)
{
int x_level = randomLevel();//获取新结点的随机层数
SkipNode<T>* new_node = nullptr;
SkipNode<T>* tmp = head;
new_node = find(key);
if (new_node) {
new_node->value = value;
cout << "This node " << key << " has already existed. And its value has been updated to " << value << endl;
return head;
}
cout << "key: " << key << ", randomLevel: " << x_level << endl;
new_node = new SkipNode<T>(key, value, x_level);
for (int i = (x_level - 1); i >= 0; i--)
{
while (tmp->next[i] != nullptr && tmp->next[i]->key < key)
{
tmp = tmp->next[i];
}
//此时tmp为第i层小于key的最近的结点,接下来完成连接即可
new_node->next[i] = tmp->next[i];
tmp->next[i] = new_node;
}
return head;
}
/*删除:
1) 用 find方法判断该结点是否存在. 如果不存在,则返回当前list, 并告知该结点不存在
2) 找到小于该结点的最近的结点
3) 更改该结点每层的前面的结点的指针*/
template<class T> SkipNode<T>* SkipList<T>::deleteNode(int key)
{
SkipNode<T>* node = find(key);
if (!node)
{
cout << "This deleting node" << key << "doesn't exist" << endl;
return head;
}
else
{
SkipNode<T>* tmp = head;
int x_level = node->next.size();
cout << "The deleting node " << key << "'s level is " << x_level << endl;
for (int i = (x_level - 1); i >= 0; i--)
{
while (tmp->next[i] != nullptr && tmp->next[i]->key < key)
{
tmp = tmp->next[i];
}
tmp->next[i] = tmp->next[i]->next[i];
cout << "This node " << key << " has been deleted from level " << i << endl;
}
return head;
}
}
int main() {
int num_of_level = 5;//5层的跳表
SkipList<int>list = SkipList<int>(num_of_level, 100);
//假设插入num_of_kv个键值对
int num_of_kv = 10;
for (int i = 0; i < num_of_kv; i++) {
list.insert(i, 100 * i);
}
//层序打印跳表
SkipNode<int>*head = list.head;
for (int i = num_of_level - 1; i >= 0; i--) {
cout << "head-->";
SkipNode<int>*tmp = head->next[i];
for (int j = 0; j < num_of_kv + 1; j++)
{
if (tmp != nullptr&&tmp->key != SkipList<int>::maxInt) {
cout << tmp->key << "-->";
}
else
{
cout << "tail";
break;
}
tmp = tmp->next[i];
}
cout << endl;
}
//删除测试
cout << "**************************删除key为5的结点后*************************" << endl;
list.deleteNode(5);
//层序打印跳表
for (int i = num_of_level - 1; i >= 0; i--) {
cout << "head-->";
SkipNode<int>*tmp = head->next[i];
for (int j = 0; j < num_of_kv + 1; j++)
{
if (tmp != nullptr&&tmp->key != SkipList<int>::maxInt) {
cout << tmp->key << "-->";
}
else
{
cout << "tail";
break;
}
tmp = tmp->next[i];
}
cout << endl;
}
system("pause");
return 0;
}