[C++]数据结构:跳表SkipList的实现与使用

#include<iostream>
#include <math.h>
using namespace std;

//E是查询值,K是返回值
template<class E,class K>
class SkipNode{
	public:
		SkipNode(int size){link=new SkipNode<E,K>*[size];}
		~SkipNode(){delete []link;}
		E data ;
		SkipNode<E,K>**link;//一维指针数组
};


template<class E,class K>
class SkipList{
	public:
		SkipList(K large,int MaxE = 10000,float p=0.5);
		//MaxE是字典的最大容量
		//一个节点既在i-1级链上又在i级链上的概率为p
		//Large是一个比字典中任意一个数均大的值,尾节点的值为Large
		//0级链上的值(不包括头结点,因其没有值)从左到右顺序排列
		~SkipList();
		bool Search(const K&k,E&e)const;
		SkipList<E,K>&Insert(const E&e);
		SkipList<E,K>&Delete(const K&k,E&e);
		void Output(ostream& out)const;  

		int Level();
		SkipNode<E,K>*SaveSearch(const K&k);
		int MaxLevel;//所允许的最大级数
		int Levels;//当前非空链的个数
		int CutOff;//用于确定级号
		K TailKey;//一个很大的key值
		SkipNode<E,K>*head;//头结点指针
		SkipNode<E,K>*tail;//尾节点指针
		SkipNode<E,K>**last;//指针数组
};


//重载操作符     
template<class E,class K>  
ostream& operator<<(ostream& out,const SkipList<E,K>&x){    
    x.Output(out);    
    return out;    
}    

//输出该跳表的内容
template<class E,class K>
void SkipList<E,K>::Output(ostream& out)const
{
	SkipNode<E,K> *y=head->link[0];
    for(;y->data!=TailKey;y=y->link[0])
    cout<<y->data<<" ";
    cout<<endl;
}


template<class E,class K>
SkipList<E,K>::SkipList(K Large,int MaxE,float p){
	CutOff=p*RAND_MAX;
	MaxLevel=ceil(log(MaxE)/log(1/p))-1;
	TailKey = Large;
	//randomize();//初始化随机发生器
	Levels = 0;//对级号进行初始化

	//创建头结点、尾节点以及数组last
	head= new SkipNode<E,K>(MaxLevel+1);
	tail= new SkipNode<E,K>(0);
	last= new SkipNode<E,K>*[MaxLevel+1];
	tail->data=Large;
	
	//将所有级都置空且将head指向tail
	for (int i=0;i<=MaxLevel;i++){
		head->link[i]=tail;
	}
}


//删除所有节点以及数组last
template<class E,class K>
SkipList<E,K>::~SkipList(){
	SkipNode<E,K>*next;

	//通过删除0级链来删除所有的节点
	while(head!=tail){
		next=head->link[0];
		delete head;
		head=next;
	}
	delete tail;
	delete []last;
}


//跳表的操作符重载
class element{
	public:
		operator long()const{return key;}
		element& operator=(long y){
			key = y;
			return *this;
		}
		int data;
		long key;
};





//搜索与k相匹配的元素,并将找到的元素放入e中
//如果不存在这样的元素则返回false
template<class E,class K>
bool SkipList<E,K>::Search(const K&k,E&e)const{
	if(k>=TailKey)
		return false;

	//调整指针p使其恰好指向可能与k匹配的节点的前一个节点
	SkipNode<E,K>*p=head;
	for (int i=Levels;i>=0;i--){
		while(p->link[i]->data<k){
			p=p->link[i];
		}
	}

	//检查是否下一个节点拥有关键值k
	e=p->link[0]->data;
	return (e==k);
}

//搜索k并且保存最终得到的位置
//在每一级链中搜索
template<class E,class K>
SkipNode<E,K>*SkipList<E,K>::SaveSearch(const K&k){
	SkipNode<E,K>*p=head;
	//调整指针p使其恰好指向可能与k匹配的节点的前一个节点
	for (int i=Levels;i>=0;i--){
		while(p->link[i]->data<k)
			p=p->link[i];
		last[i]=p;
	}
	return (p->link[0]);
}

//产生一个随机级号<=MaxLevel
template<class E,class K>
int SkipList<E,K>::Level(){
	int lev = 0;
	while(rand()<=CutOff)
		lev++;
	return (lev<=MaxLevel)?lev:MaxLevel;
}

class BadInput{
	public:
		BadInput(){
			cout<<"Bad Input!"<<endl;
		}
};


//若不存在重复则插入e
template<class E,class K>
SkipList<E,K>& SkipList<E,K>::Insert(const E&e){
	K k = e;
	if(k>=TailKey)
		throw BadInput();//关键值太大了
	
	//检验是否重复
	SkipNode<E,K>*p=SaveSearch(k);
	if(p->data==e)
		throw BadInput();//关键值重复

	//不重复则为新节点创建级号
	int lev = Level();
	//fix level to be <=Levels+1
	if (lev>Levels)
	{
		lev=++Levels;
		last[lev]=head;
	}

	//产生新节点并且将其插入在p之后
	SkipNode<E,K>*y = new SkipNode<E,K>(lev+1);
	y->data=e;
	for (int i=0;i<=lev;i++){
		//插入到第i级链
		y->link[i]=last[i]->link[i];
		last[i]->link[i]=y;
	}
	return *this;
}

//从跳表中删除与k相匹配的元素并将其放到e
//如果不存在则引发异常BadInput
template<class E,class K>
SkipList<E,K>& SkipList<E,K>::Delete(const K&k,E&e){
	if(k>=TailKey)
		throw BadInput();//关键值太大
	
	//检查是否存在与k相匹配的元素
	SkipNode<E,K>*p=SaveSearch(k);
	if(p->data!=k)
		throw BadInput();//不存在
	
	//从跳表中删除节点
	for (int i=0;i<=Levels&&last[i]->link[i]==p;i++)
		last[i]->link=p->link[i];

	//修改级数
	while(Levels>0&&head->link[Levels]==tail)
		Levels--;

	e=p->data;
	delete p;
	return *this;
}


void main(){
	SkipList<long,float>mySkip(1000);
	mySkip.Insert(100);
	mySkip.Insert(123);
	mySkip.Insert(12.13);
	mySkip.Insert(10.30);
	mySkip.Insert(124);
	cout<<"CutOff:"<<mySkip.CutOff<<endl;
	cout<<"MaxLevel:"<<mySkip.MaxLevel<<endl;
	cout<<"Level:"<<mySkip.Level()<<endl;
	cout<<"tail:"<<mySkip.tail<<endl;
	cout<<"TailKey:"<<mySkip.TailKey<<endl;
	cout<<mySkip<<endl;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值