跳表

跳表

跳表是为了降低链表的复杂度,在链表中间的节点中加入一个指针

-首先其数据成员
1、用于往链表中插入数据确定其级数
2、当前最大的级数
3、允许的最大级数
4、链表当前大小
5、首节点
6、尾节点
7、用于查找数据时确定所有层数的最后一个节点(不是某一层真的最后一个节点,只是要插入位置的前面节点的最后一个)
8、最大关键字

    float cutOff;//用来确定层数
	int levels;  //当前最大的非空链表
	int dSize;   //字典的数对个数
	int maxLevel;//允许的最大链表层数
	K tailKey;   //最大关键字
	skipNode<K, E>* headerNode; //头节点指针
	skipNode<K, E>* tailNode;   //尾节点指针
	skipNode<K, E>** last;      //last[i]表示i层的最后节点

成员函数

  • 构造函数
template<class K,class E>
skipList<K, E>::skipList(K largeKey, int maxPairs, float prob)
{//构建函数,关键字小于largeKey且size最多为maxPairs. 0<prob<1;
	cutOff = prob * RAND_MAX;
	tailKey = largeKey;
	dSize = 0;
	levels = 0;
	maxLevel = maxPairs;

	//生成头节点、尾节点和数组last
	pair<K, E> tailPair;
	tailPair.first = tailKey;
	headerNode = new skipNode<K, E>(tailPair, maxLevel + 1);
	tailNode = new skipNode<K, E>(tailPair, 0);

	//当链表为空,头节点有maxLevel+1个指向尾节点的指针
	for (int i = 0; i <= maxLevel; i++)
	{
		headerNode->next[i] = tailNode;
	}
}
  • 查找函数
template<class K,class E>
skipNode<K, E>* skipList<K, E>::search(const K& k)const
{
	skipNode<K, E>* temp = headerNode;
	//从上层链表到下层遍历
	for (int i = levels; i >=0; i--)
	{
		while (temp->next[i]->element.first<k)
		{
			temp = temp->next[i];
		}
		last[i] = temp;
	}
	return temp->next[0];
}

查找函数将小于要查找数每一层的最后一个节点放入last----last[i] = temp;返回的是第一个不小于查找数的节点,但并不一定是要找的

  • 分配级数函数
template<class K,class E>
int skipList<K, E>::level()const
{
	int lev = 0;
	while (rand()<=cutOff)
	{
		lev++;
	}
	return (level <= maxLevel) ? lev : maxLevel;
}

分配级数也可以将随机数生成器产生的数分几段:第一段(1~1/p)…

  • 插入函数
template<class K,class E>
void skipList<K, E>::insert(const pair<const K, E>& thePair)
{//把数对thePair插入字典,覆盖其关键字相同的已存在的数对
	if (thePair.first>=tailKey)
	{//关键字太大
		ostringstream s;
		s << "Key = " << thePair.first << " nust be < " << tailKey;
		throw illegalParameterValue(s.str());
	}
	//查看关键字为theKey的数对是否存在
	skipNode<K, E>* temp = search(thePair.first);
	if (temp->element.first==thePair.first)
	{//存在
		temp->element.second = thePair.second;
		return;
	}

	//不存在
	int theLevel = level();
	if (theLevel>levels)
	{
		theLevel = ++levels;
		last[theLevel] = headerNode;
	}
	//插入新节点
	skipNode<K, E>* newNode = new skipNode<K, E>(thePair, theLevel + 1);
	for (int i = 0; i <= theLevel; i++)
	{
		newNode->next[i] = last[i]->next[i];
		last[i]->next[i] = newNode;
	}
	dSize++;
	return;
}

插入函数中:

if (theLevel>levels)
	{
		theLevel = ++levels;
		last[theLevel] = headerNode;
	}

使插入函数级数最大为当前级数+1;并将其作为当前级数

//插入新节点
	skipNode<K, E>* newNode = new skipNode<K, E>(thePair, theLevel + 1);
	for (int i = 0; i <= theLevel; i++)
	{
		newNode->next[i] = last[i]->next[i];
		last[i]->next[i] = newNode;
	}

将要插入的节点插入不大于theLevel所有层最后一个节点的后面

  • 删除节点函数
template<class K,class E>
void skipList<K, E>::erase(const K& k)
{
	//链表中没有
	if (k>=tailKey)
	{
		return;
	}
	//判断是否有匹配的
	skipNode<K, E>* temp = search(k);
	if (temp->element.first!=k)
	{//不存在
		return;
	}

	//从链表中删除节点
	for (int i = 0; i <= levels&&last[i]->next[i]==temp; i--)
	{
		last[i]->next[i] = temp->next[i];
	}

	//更新链表级
	while (levels>0&&headerNode->next[levels]==tailNode)
	{
		levels--;
	}
	delete temp;
	dSize--;

}

删除函数中while (levels>0&&headerNode->next[levels]==tailNode),表示删除的节点为当前级数节点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值