跳表(C++实现)

跳表也是key-value的形式存储,跳表(skip list) 对标的是平衡二叉树(AVL Tree),是一种插入/删除/搜索都是O(logn)的数据结构。在一些热门的项目里用来替代平衡二叉树,如redis,leveldb等。
我的理解:跳表其实就是建立多层索引(多层链表)。
显然:每列的key值都是一样的。此外,每个结点到底有多少层是由概率来计算的。
跳表(C++实现)_第1张图片
上图跳表中的数字是key值,可见,如果要查找key值为12的结点,从head结点开始,5跳就可以找到了。具体的跳跃规则写在代码中了。

SkipNode

每个结点都有一个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);
	}
}

SkipList

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);
};

跳表初始化(确定maxLevel,初始化头结点和尾结点)

跳表(C++实现)_第2张图片

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;
}

跳表(C++实现)_第3张图片

你可能感兴趣的:(跳表(C++实现))