您的位置:首页 > 编程语言 > C语言/C++

跳跃表(Skip List)的实现及测试 C++实现

2015-07-06 09:42 525 查看
//skipnode.h头文件:
#include<vector>
using namespace std;
struct skipnode//表示一个结点的结构体
{
int data;//元素的值
int level;//层数
vector<skipnode * >p;//存结点指针的数组
skipnode(int datain=0,int levelin=1){//构造函数
setnode(datain,levelin);
}
void setnode(int datain=0,int levelin=1){//设置数据成员,设置数组p的长度并在里面赋空值
data=datain;
level=levelin;
while(!p.empty())
p.pop_back();
for(int i=0;i<level;i++){
p.push_back(NULL);
}
}
};
//skiplist.h头文件:
#include<vector>
#include<iostream>
#include <stdlib.h>
#include <time.h>
#include <cmath>
#include "skipnode.h"
using namespace std;
class skiplist
{
int level,maxlevel;
int tailkey;
skipnode * head;
skipnode * tail;
public:
skiplist(int tailkeyin=2000000,int inmaxlevel=30){//构造函数,构造一个空跳跃表
level=1;
tailkey=tailkeyin;
maxlevel=inmaxlevel;
head=new skipnode(-1,maxlevel+1);
tail=new skipnode(tailkeyin,maxlevel+1);
for(int i=0;i<maxlevel;i++){
head->p.at(i)=tail;
}
}
~skiplist(){//析构函数
clear();
delete head;
delete tail;
}
int getlevel(){//获取当前跳跃表的层数
return level;
}
void clear(){//清空跳跃表
if(head->p.at(0)!=tail){
skipnode * ptr=head->p.at(0);//游标
while(ptr->p.at(0)!=tail){
skipnode * qian=ptr;
ptr=ptr->p.at(0);
delete qian;
}
for(int i=0;i<maxlevel;i++){
head->p.at(i)=tail;
}
level=1;
}
}
void print(){//显示跳跃表的内容
for(int i=0;i<level;i++){
skipnode * ptr;//游标
ptr=head;
cout<<"第"<<i<<"层: head->";
while(ptr->p.at(i)!=tail){
cout<<ptr->p.at(i)->data<<"->";
ptr=ptr->p.at(i);
}
cout<<"tail"<<endl;
}
}
int setgrade(float p=0.5){//生成新点的层数,默认的概率因子为0.5
int grade=1;
float r;
float m=RAND_MAX;
while(true){
r=rand()/m;
if(r<p)
grade++;
else break;
}
if(grade>maxlevel)
grade=maxlevel;
return grade;
}
void insert(int indata=0,float p2=0.5){//插入新点
int inlev=setgrade(p2);
if(level<inlev)
level=inlev;
skipnode * ptr;//游标指针
ptr=head;//初始化游标指针
vector<skipnode * >location;//用来存插入的位置的指针数组
location.resize(inlev);
for(int kk=level-1;kk>inlev-1;){
if(indata<ptr->p.at(kk)->data){//向下搜索
kk--;
}
else{//向右搜索
ptr=ptr->p.at(kk);
}
}
for(;kk>=0;){
if(indata<ptr->p.at(kk)->data){//向下搜索
location.at(kk)=ptr;
kk--;
}
else{//向右搜索
ptr=ptr->p.at(kk);
}
}
skipnode * n1;
n1=new skipnode(indata,inlev);
for(int i=0;i<inlev;i++){
n1->p.at(i)=location.at(i)->p.at(i);
location.at(i)->p.at(i)=n1;

}
}
bool exist(int indata){//检查一个点是否存在
bool exi=false;
skipnode * ptr;//游标指针
ptr=head;//初始化游标指针
for(int kk=level-1;kk>=0;){
if(indata==ptr->p.at(kk)->data){//停止搜索
exi=true;
break;
}
else if(indata<ptr->p.at(kk)->data){//向下搜索
kk--;
}
else{//向右搜索
ptr=ptr->p.at(kk);
}
}
return exi;
}
skipnode * search(int indata){//返回要查找的点的指针,如果不存在则返回尾指针
skipnode * ptr;//游标指针
ptr=head;//初始化游标指针
for(int kk=level-1;kk>=0;){
if(indata==ptr->p.at(kk)->data){//停止搜索
return ptr->p.at(kk);
}
else if(indata<ptr->p.at(kk)->data){//向下搜索
kk--;
}
else{//向右搜索
ptr=ptr->p.at(kk);
}
}//如果不存在则返回尾结点的指针
return tail;
}
void remove(int indata){//删除结点
skipnode * ptr;//游标指针
ptr=head;//初始化游标指针
skipnode * d1;
for(int kk=level-1;kk>=0;){
if(indata==ptr->p.at(kk)->data){//停止搜索

d1=ptr->p.at(kk);
ptr->p.at(kk)=ptr->p.at(kk)->p.at(kk);
//
kk--;
}
else if(indata<ptr->p.at(kk)->data){//向下搜索
kk--;
}
else{//向右搜索
ptr=ptr->p.at(kk);
}
}
delete d1;
for(kk=level-1;kk>=0;kk--){
if(head->p.at(kk)==tail)
level--;
else break;
}
}
};
主函数:
#include<iostream>
#include<vector>
#include<cmath>
#include <time.h>
#include <algorithm>
#include<numeric>
#include "skiplist.h"
using namespace std;
#define E exp(1)
int main(){
vector<double>inserttime,searchtime,removetime;
vector<int>levellist;
float p=1.0/E;//概率因子
int ntime=100;//试验次数
for(int kk=1;kk<=ntime;kk++){
skiplist list;
srand((int)time(NULL));
vector<int>number;
for(int i=1;i<=1000000;i++){
number.push_back(i);
}
random_shuffle(number.begin(),number.end());//生成乱序的1到n的数
double start,end,cost;
start=clock();
for(i=0;i<number.size();i++){
list.insert(number.at(i),p);
}
end=clock();
cost=end-start;
//cout<<"插入一共运行了"<<cost<<"毫秒"<<endl;
//cout<<"跳跃表有"<<list.getlevel()<<"层"<<endl;
inserttime.push_back(cost);
levellist.push_back(list.getlevel());
random_shuffle(number.begin(),number.end());//生成乱序的1到n的数
start=clock();
for(i=0;i<number.size();i++){
list.search(number.at(i));
}
end=clock();
cost=end-start;
//cout<<"查找一共运行了"<<cost<<"毫秒"<<endl;
searchtime.push_back(cost);
random_shuffle(number.begin(),number.end());//生成乱序的1到n的数
start=clock();
for(i=0;i<number.size();i++){
list.remove(number.at(i));
}
end=clock();
cost=end-start;
//cout<<"删除一共运行了"<<cost<<"毫秒"<<endl;
removetime.push_back(cost);
}
double inserttimemean,searchtimemean,removetimemean,levelmean;
double zero=0;
double size=ntime;
inserttimemean=accumulate(inserttime.begin(), inserttime.end(),zero)/size;
levelmean=accumulate(levellist.begin(), levellist.end(),zero)/size;
searchtimemean=accumulate(searchtime.begin(), searchtime.end(),zero)/size;
removetimemean=accumulate(removetime.begin(), removetime.end(),zero)/size;
cout<<"概率因子为"<<p<<endl;
cout<<"测试了"<<ntime<<"次"<<endl;
cout<<"每次插入数据平均用时"<<inserttimemean<<"毫秒"<<endl;
cout<<"跳跃表平均层数为"<<levelmean<<"层"<<endl;
cout<<"每次查找数据平均用时"<<searchtimemean<<"毫秒"<<endl;
cout<<"每次删除数据平均用时"<<removetimemean<<"毫秒"<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息