数据结构、算法与应用 第十章 跳表 skip

这是一个关于使用跳跃列表(Skip List)实现字典数据结构的代码实现。跳跃列表是一种高效的数据结构,支持快速查找、插入和删除操作。代码中定义了`skipNode`结构体,表示具有`next`指针数组的节点,以及`skipList`类,实现了字典的基本操作,如查找、插入和删除。类中包含了随机确定节点级别的逻辑,并维护了一个`last`数组来辅助操作。
摘要由CSDN通过智能技术生成
//跳过列表中使用的节点类型
//具有下一个和元素字段的节点;元素是一对<const K,E>
//接下来是指针的一维数组

#ifndef SKIPNODE_H
#define SKIPNODE_H

template<typename K, typename E>
struct skipNode
{
	typedef pair<const K, E> pairType;
	pairType element;
	skipNode<K, E> **next;     // 指针数组

	skipNode(const pairType& thePair, int size) : element(thePair){next = new skipNode<K, E>* [size];}
};

#endif // !SKIPNODE_H
// 跳表数据结构,实现字典

#ifndef SKIPLIST_H
#define SKIPLIST_H

#include <iostream>
#include <math.h>
#include "dictionary.h"
#include "skipNode.h"
#include "myExceptions.h"

template<typename K, typename E>
class skipList : public dictionary<K, E>
{
public:
	skipList(K, int maxPairs = 10000, float prob = 0.5);
	~skipList();

	bool empty() const {return dSize == 0;}
	int size() const {return dSize;}
	pair<const K, E>* find(const K&) const;
	void erase(const K&);
	void insert(const pair<const K, E>&);
	void output(ostream& out) const;

protected:
	float cutOff;                             // 用来的确定层数
	int level() const;                        // 生成一个随机级别数
	int levels;                               // 当前最大的非空链表
	int dSize;                                // 字典的数对个数
	int maxLevel;                             // 允许的最大链表层数
	K tailKey;                                // 最大挂按键自

	skipNode<K, E>* search(const K&) const;   // 搜索保存最后的节点
	skipNode<K, E>* headerNode;               // 头节点指针
	skipNode<K, E>* tailNode;                 // 尾结点指针
	skipNode<K, E>** last;                    // last[i] 表示 i 层的最后节点
};

template<typename K, typename E>
                           // 关键字       数对          概率
skipList<K, E>::skipList(K largeKey, int maxPairs, float prob)
{// 构造函数,关键字小于 largeKey 且数对个数 size 最多为 maxPairs。0 < prob < 1
	cutOff = prob * RAND_MAX;     // 32767
	maxLevel = (int) ceil(logf((float)maxPairs) / logf(1 / prob));   // ceil 取整  logf 返回以 e 为底单精度数的对数值
	levels = 0;      // 初始化级数
	dSize = 0;
	tailKey = largeKey;  // 最大关键字

	// 生成头结点、尾结点和数组 last
	pair<K, E> tailPair;
	tailPair.first = tailKey;      // 最大关键字
	headerNode = new skipNode<K, E> (tailPair, maxLevel + 1);    // 头节点指针
	tailNode = new skipList<K, E> (tailPair, 0);
	last = new skipNode<K, E>* [maxLevel + 1];   // 允许最大的链表层数

	// 链表为空时,任意级链表中的头节点都指向尾节点
	for (int i = 0; i <= maxLevel; i++)
		headerNode->next[i] = tailNode;
}

template<class K, class E>
skipList<K,E>::~skipList()
{// 析构函数 最后删除所有节点和数组
   skipNode<K,E> *nextNode;

   // 按照 0 级链删除所有节点
   while (headerNode != tailNode)
   {
      nextNode = headerNode->next[0];
      delete headerNode;
      headerNode = nextNode;
   }
   delete tailNode;

   delete [] last;
}

template<typename K, typename E>
pair<const K, E>* skipList<K, E>::find(const K& theKey) const
{// 返回匹配的数对的指针
	// 如果没有匹配的数对,返回NULL
	if (theKey >= tailKey)
		return NULL;         // 没有可能的匹配的数对

	// 位置 beforeNode 是关键字为 theKey 的节点之前最右边的位置
	skipNode<K, E>* beforeNode = headerNode;
	for (int i = levels; i >= 0; i--)      // 从上级链表到下级链表
		// 跟踪 i 级链表指针
		while (beforeNode->next[i]->element.first < theKey)
			beforeNode = beforeNode->next[i];

	return NULL;  // 无匹配的数对
}

template<typename K, typename E>
int skipList<K, E>::level() const
{// 返回一个表示链表级的随机数,这个数不大于 maxLevel
	int lev = 0;
	while (rand() <= cutOff)
		lev++;
	return (lev <= maxLevel) ? lev : maxLevel;
}

template<typename K, typename E>
skipNode<K, E>* skipList<K, E>::search(const K& theKey) const
{// 搜索关键字 theKey,把每一级链表中要查看的最后一个节点存储在数组 last中
	// 返回包含关键字 theKey 的节点
	// 位置 beforeNode 是关键字为 theKey 的节点之前最右边的位置
	skipNode<K, E>* beforeNode = headerNode;
	for (int i = levels; i >= 0; i--)
	{
		while (beforeNode->next[i]->element.first < theKey)
			beforeNode = beforeNode->next[i];
		last[i] = beforeNode;              // 最后一级链表 i 的节点
	}
	return beforeNode->next[0];
}

template<typename K, typename E>
void skipList<K, E>::insert(const pair<const K, E>& thePair)
{// 把数对 thePair 插入字典,覆盖其关键字相同的已存在的数对
	if (thePair.first >= tailKey)          // 关键字太大
	{
		ostringstream s;
		s << "Key = " << thePair.first << " 必须小于 " << tailKey;
		throw illegalParameterValue(s.str());
	}

	// 查看关键字为 theKey 的数对是否已经存在
	skipNode<K, E>* theNode = search(thePair.first);
	if (theNode->element.first == thePair.first)
	{// 若存在,则更新该数对的值
		theNode->element.second = thePair.second;
		return;
	}

	// 若不在,则确定新节点所在的级链表
	int theLevel = level();           // 新节点的级
	// 使级 theLevel 为 <= levels + 1
	if (theLevel > levels)
	{
		theLevel = ++levels;
		last[theLevel] = headerNode;
	}

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

	dSize++;
	return;
}

template<typename K, typename E>
void skipList<K, E>::erase(const K& theKey)
{// 删除关键字等于 theKey 的数对
	if (theKey >= tailKey)         // 关键字太大
		return;

	// 查看是否有匹配的数对
	skipNode<K, E>* theNode = search(theKey);
	if (theNode->element.first != theKey)       // 不存在
		return;

	// 从跳表中删除节点
	for (int i = 0; i <= levels && last[i]->next[i] == theNode; i++)
		last[i]->next[i] = theNode->next[i];

	// 更新链表级
	while (levels > 0 && headerNode->next[levels] == tailNode)
		levels--;
	delete theNode;
	dSize--;
}
#endif // !SKIPLIST_H

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值