跳跃表(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; }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(七):数据结构详解
- Lua教程(二):C++和Lua相互传递数据示例
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- C#数据结构揭秘一
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C++联合体转换成C#结构的实现方法
- C#实现的算24点游戏算法实例分析
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题