c_cpp 【随机化算法】跳跃表【7.3.3】舍伍德(舍伍德)算法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 【随机化算法】跳跃表【7.3.3】舍伍德(舍伍德)算法相关的知识,希望对你有一定的参考价值。

//随机化算法 跳跃表
#include "stdafx.h"
#include "RandomNumber.h"
#include <cmath>
#include <iostream>
using namespace std;
 
template<class EType,class KType> class SkipList;
template<class EType,class KType>
class SkipNode
{
	friend SkipList<EType,KType>;
	private:
		SkipNode(int size)
		{
			next = new SkipNode<EType,KType>*[size];
		}
		~SkipNode()
		{
			delete []next;
		}
		EType data;//集合中的元素
		SkipNode<EType,EType> **next;//指针数组 next[i]是第i级指针
};
 
template<class EType,class KType>
class SkipList
{
	public:
		SkipList(KType Large,int MaxE = 10000,float p = 0.5);
		~SkipList();
		bool Search(const KType& k,EType& e) const;
		SkipList<EType,KType>& Insert(const EType& e);
		SkipList<EType,KType>& Delete(const KType& k,EType& e);
		void Output();
	private:
		int Level();
		SkipNode<EType,KType> *SaveSearch(const KType& k);
		int MaxLevel;					//跳跃表级别上界
		int Levels;						//当前最大级别
		RandomNumber rnd;				//随机数产生器
		float Prob;						//用于分配节点级别
		KType TailKey;					//元素键值上界
		SkipNode<EType,KType> *head;	//头结点指针
		SkipNode<EType,KType> *NIL;		//尾节点指针
		SkipNode<EType,KType> **last;	//指针数组
};
 
//构造函数
template<class EType,class KType>
SkipList<EType,KType>::SkipList(KType Large,int MaxE,float p)
{
	Prob = p;
	MaxLevel = ceil(log(float(MaxE))/log(1/p))-1;		//初始化跳跃表级别上界
	TailKey = Large;							//元素键值上界
	Levels = 0;									//初始化当前最大级别
 
	//创建头、尾节点和数组 last
	head = new SkipNode<EType,KType>(MaxLevel+1);
	NIL = new SkipNode<EType,KType>(0);
	last = new SkipNode<EType,KType> *[MaxLevel+1];
	NIL->data = Large;
 
	//将跳跃表初始化为空表
	for(int i=0; i<=MaxLevel; i++)
	{
		head->next[i] = NIL;
	}
}
 
//析构函数
template<class EType,class KType>
SkipList<EType,KType>::~SkipList()
{
	SkipNode<EType,KType> *next;
 
	//删除所有节点
	while(head!=NIL)
	{
		next = head->next[0];
		delete head;
		head = next;
	}
 
	delete NIL;
	delete []last;
}
 
class element
{
	friend int main(void);
	public:
		operator long() const 
		{
			return key;
		}
		element& operator = (long y)
		{
			key = y;
			return *this;
		}
	private:
		int data;
		long key;
};
 
//搜索指定元素k
template<class EType,class KType>
bool SkipList<EType,KType>::Search(const KType& k,EType& e) const
{
	if(k>=TailKey)
	{
		return false;
	}
	//位置p恰好位于指定元素k之前
	SkipNode<EType,KType> *p = head;
	for(int i=Levels; i>=0; i--)//逐渐向下搜索
	{
		while(p->next[i]->data<k)//在第i级链中搜索
		{
			p = p->next[i];//每次搜索尽可能滴接近要搜索的元素
		}
	}
	e = p->next[0]->data;
	return (e==k);
}
 
//搜索指定元素k,并将每一级中遇到的上一个节点存放在数组last中
template<class EType,class KType>
SkipNode<EType,KType> *SkipList<EType,KType>::SaveSearch(const KType& k)
{
	//位置p恰好位于指定元素k之前
	SkipNode<EType,KType> *p = head;
	for(int i = Levels; i>=0; i--)
	{
		while(p->next[i]->data<k)
		{
			p = p->next[i];
		}
		last[i] = p;	//上一个第i级结点
	}
	return (p->next[0]);
}
 
//产生不超过MaxLevel 的随机级别
template<class EType,class KType>
int SkipList<EType,KType>::Level()
{
	int lev = 0;
	while(rnd.fRandom()<Prob)
	{
		lev++;
	}
	return (lev<=MaxLevel)?lev:MaxLevel;
}
 
//插入指定元素e
template<class EType,class KType>
SkipList<EType,KType>& SkipList<EType,KType>::Insert(const EType& e)
{
	KType k = e;//取得元素键值
	if(k>=TailKey)
	{
		cout<<"元素键值超界!"<<endl;
		return *this;
	}
	//检查元素是否已存在
	SkipNode<EType,KType> *p = SaveSearch(k);
	if(p->data == e)
	{
		cout<<"元素已存在!"<<endl;
		return *this;
	}
 
	//元素不存在,确定新节点级别
	int lev = Level();
	//调整个级别指针
	if(lev>Levels)
	{
		for(int i=Levels+1; i<=lev; i++)
		{
			last[i] = head;
		}
		Levels = lev;
	}
 
	//产生新节点,并将新节点插入p之后
	SkipNode<EType,KType> *y = new SkipNode<EType,KType>(lev+1);
	y->data = e;
 
	for(int i=0; i<=lev; i++)
	{
		//插入第i级链
		y->next[i] = last[i]->next[i];
		last[i]->next[i] = y;
	}
	return *this;
}
 
//删除键值为k的元素,并将所删除的元素存入e
template<class EType,class KType>
SkipList<EType,KType>& SkipList<EType,KType>::Delete(const KType& k,EType& e)
{
	if(k>=TailKey)
	{
		cout<<"元素键值超界!"<<endl;
	}
	//搜索待删除元素
	SkipNode<EType,KType> *p = SaveSearch(k);
	if(p->data!=k)
	{
		cout<<"未找到待删除元素!"<<endl;
	}
	//从跳跃表中删除节点
	for(int i=0; i<=Levels && last[i]->next[i] == p; i++)
	{
		last[i]->next[i] = p->next[i];
	}
	//更新当前级别
	while(Levels>0 && head->next[Levels] == NIL)
	{
		Levels--;
	}
	e = p->data;
	delete p;
	return *this;
}
 
//输出集合中的元素
template<class EType,class KType>
void SkipList<EType,KType>::Output()
{
	SkipNode<EType,KType> *y = head->next[0];
	for(;y!=NIL; y=y->next[0])
	{
		cout<<y->data<<' ';
	}
	cout<<endl;
}
 
int main()
{
	SkipList<int,int> *s = new SkipList<int,int>(100,10,0.5);
 
	//创建
	cout<<"=========创建==========="<<endl;
 
	int a[] = {5,3,2,11,7,13,19,17,23};
 
	for(int i=0; i<9; i++)
	{
		s->Insert(a[i]);
	}
	s->Output();
 
	//搜索
	cout<<"=========搜索==========="<<endl;
	int k=17,e;
	cout<<"搜索元素k="<<k<<"如下:"<<endl;
	if(s->Search(17,e))
	{
		cout<<"位置搜索结果为:k="<<k<<",e="<<e;
	}
	cout<<endl;
 
	//删除
	cout<<"=========删除==========="<<endl;
	cout<<"删除跳跃表元素k="<<k<<"剩余元素如下:"<<endl;
	s->Delete(k,e);
	s->Output();
 
	delete s;
	return 0;
}
#include"time.h"
//随机数类
const unsigned long maxshort = 65536L;
const unsigned long multiplier = 1194211693L;
const unsigned long adder = 12345L;
 
class RandomNumber
{
	private:
		//当前种子
		unsigned long randSeed;
	public:
		RandomNumber(unsigned long s = 0);//构造函数,默认值0表示由系统自动产生种子
		unsigned short Random(unsigned long n);//产生0:n-1之间的随机整数
		double fRandom(void);//产生[0,1)之间的随机实数
};
 
RandomNumber::RandomNumber(unsigned long s)//产生种子
{
	if(s == 0)
	{
		randSeed = time(0);//用系统时间产生种子
	}
	else
	{
		randSeed = s;//由用户提供种子
	}
}
 
unsigned short RandomNumber::Random(unsigned long n)//产生0:n-1之间的随机整数
{
	randSeed = multiplier * randSeed + adder;//线性同余式
	return (unsigned short)((randSeed>>16)%n);
}
 
double RandomNumber::fRandom(void)//产生[0,1)之间的随机实数
{
	return Random(maxshort)/double(maxshort);
}

以上是关于c_cpp 【随机化算法】跳跃表【7.3.3】舍伍德(舍伍德)算法的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 【随机化算法】线性时间选择算法【7.3.1】舍伍德(舍伍德)算法

舍伍德算法 跳跃表增删查的实现

随机化算法概述

随机化算法概述

c_cpp 【随机化算法】随机数【7.1】

数据结构——跳跃表