【高阶数据结构】跳表

SkipList是由William Pugh发明的:

William Pugh一开始的思路:

  • 每隔一个节点就提高一层;

【高阶数据结构】跳表_第1张图片

查找的效率为O(log(N))

但是他有一个非常大的问题:就是如果删除一个元素那么原先的结构就被打乱,需要从新调整;时间复杂度:O(N); 

SkipList设计

William Pugh进一步优化:将每一个节点的层数进行随机,不采用隔一个节点就上升一层

节点代码:节点的数值、一个指针数组(指向下一个节点)

template
struct SkipNode
{
	SkipNode(T val, size_t n):_val(val)
	{
		_v.resize(n, nullptr);
	}
	//成员变量
	T _val;
	vector*> _v;
};

查找一个值:

  • 下一个元素为空或者比要找的元素大向下,保存当前指针,下一个元素为空或者比要找的元素小向右
  • 返回值为pair, bool>,vector是后续插入元素的前一个,bool决定是否存在
	//应该返回查找链
	pair, bool> FindPervNode(T val)
	{
		vector findList(_head->_v.size(), nullptr);//查找链

		int level = _head->_v.size() - 1;
		Node* cur = _head;
		//下标为-1,说明没有元素;
		while (level >= 0)
		{
			//下一个元素为空或者比要找的元素大 , 向下
			if (cur->_v[level] == nullptr || cur->_val > val)
			{
				//前一个添加查找链
				findList[level] = cur;
				level--;
			}
			//下一个元素比要找的元素小,向右
			else if(cur->_val < val)
			{
				cur = cur->_v[level];
			}
			//等于,return false
			else
				return make_pair(findList, true);
		}
		return make_pair(findList, false);
	}

如何插入:

  • 使用查找判断是否已存在,并且找插入位置的前一个的查找链
  • 插入元素的next等于前一个的next;前一个的next等于插入元素;

【高阶数据结构】跳表_第2张图片

	//应该返回查找链
	pair, bool> FindPervNode(T val)
	{
		vector findList(_head->_v.size(), nullptr);//查找链

		int level = _head->_v.size() - 1;
		Node* cur = _head;
		//下标为-1,说明没有元素;
		while (level >= 0)
		{
			//下一个元素为空或者比要找的元素大 , 向下
			if (cur->_v[level] == nullptr || cur->_val > val)
			{
				//前一个添加查找链
				findList[level] = cur;
				level--;
			}
			//下一个元素比要找的元素小,向右
			else if(cur->_val < val)
			{
				cur = cur->_v[level];
			}
			//等于,return false
			else
				return make_pair(findList, true);
		}
		return make_pair(findList, false);
	}

删除:

  • 每个元素至少有一层,遍历最底层;保存前一个
  • 使用前一个的next等于删除元素的next;
  • delete删除元素; 
bool Erase(T val)
	{
		//查找是否存在
		pair, bool> fpn = FindPervNode(val);

		if (fpn.second == false)
			return false;

		vector findList = fpn.first;
		Node* prev = findList[0], * cur = prev->_v[0];
		//前一个节指向  删除节点的后一个节点
		for (int i = 0; i < cur->_v.size(); i++)
		{
			prev->_v[i] = cur->_v[i];
		}
		delete cur;

		// 如果删除最高层节点,把头节点的层数也降一下
		int i = _head->_v.size() - 1;
		while (i >= 0)
		{
			if (_head->_v[i] == nullptr)
				--i;
			else
				break;
		}
		_head->_v.resize(i + 1);
		return true;
	}

完整代码:

#pragma once
#include
#include

using namespace std;

template
struct SkipNode
{
	SkipNode(T val, size_t n):_val(val)
	{
		_v.resize(n, nullptr);
	}
	//成员变量
	T _val;
	vector*> _v;
};

template
class SkipList {
	typedef SkipNode Node;
public:
	//应该返回查找链
	pair, bool> FindPervNode(T val)
	{
		vector findList(_head->_v.size(), nullptr);//查找链

		int level = _head->_v.size() - 1;
		Node* cur = _head;
		//下标为-1,说明没有元素;
		while (level >= 0)
		{
			//下一个元素为空或者比要找的元素大 , 向下
			if (cur->_v[level] == nullptr || cur->_val > val)
			{
				//前一个添加查找链
				findList[level] = cur;
				level--;
			}
			//下一个元素比要找的元素小,向右
			else if(cur->_val < val)
			{
				cur = cur->_v[level];
			}
			//等于,return false
			else
				return make_pair(findList, true);
		}
		return make_pair(findList, false);
	}
	int Random()
	{
		int level = 1;
		while (rand() <= _proba * RAND_MAX && level < _maxLevel)
			level++;
		return level;
	}
	bool Insert(T val)
	{
		//查找是否存在
		pair, bool> fpn = FindPervNode(val);
		 
		if (fpn.second == true)
			return false;

		vector findList= fpn.first;
		//获取随机层数和新节点
		int probaLevel = Random();
		Node* newNode = new Node(val,probaLevel);
		//头的个数小于新节点的个数,扩容
		if (_head->_v.size() < probaLevel)
		{
			_head->_v.resize(probaLevel, nullptr);
			findList.resize(probaLevel, _head);
		}
		
		//新节点指向findlist的下一个,findlist指向新节点
		for (int i = 0; i < probaLevel; i++)
		{
			newNode->_v[i] = findList[i]->_v[i];
			findList[i]->_v[i] = newNode;
		}
	}
	bool Erase(T val)
	{
		//查找是否存在
		pair, bool> fpn = FindPervNode(val);

		if (fpn.second == false)
			return false;

		vector findList = fpn.first;
		Node* prev = findList[0], * cur = prev->_v[0];
		//前一个节指向  删除节点的后一个节点
		for (int i = 0; i < cur->_v.size(); i++)
		{
			prev->_v[i] = cur->_v[i];
		}
		delete cur;

		// 如果删除最高层节点,把头节点的层数也降一下
		int i = _head->_v.size() - 1;
		while (i >= 0)
		{
			if (_head->_v[i] == nullptr)
				--i;
			else
				break;
		}
		_head->_v.resize(i + 1);
		return true;
	}
	void Print()
	{

		Node* cur = _head;
		while (cur)
		{
			printf("%2d\n", cur->_val);
			// 打印每个每个cur节点
			for (auto e : cur->_v)
			{
				printf("%2s", "↓");
			}
			printf("\n");

			cur = cur->_v[0];
		}
	}
public:
	SkipList()
	{
		srand( (unsigned int) time(nullptr) );
		_head = new Node(T(), 1);
		_proba = 0.5;
		_maxLevel = 32;
	}
	~SkipList()
	{
		if (_head)
		{
			//删除所有节点
		}
	}

private:
	//头节点
	Node* _head;
	//每多一层的概率
	float _proba;
	//最大层数
	size_t _maxLevel;
};

你可能感兴趣的:(数据结构,数据结构,算法)