虽然avl树和红黑树在数据搜索和排序方面都是有效的数据结构,但是都显得特别麻烦,跳跃表就显得特别简单,虽然简单 不影响他性能,在平均情况下,其插入、删除、查找数据时间复杂度都是O(log(N)),其最坏情况下都为O(N)。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      跳跃表的构造源于一种用于查找的基础数据结构---链表。跳跃表就是在普通链表的情况下,随机在一些节点上增加几层链,用于指向后面的数据。

普通链表    :

         

 

跳跃表:                                            

 

 

  链表就像走楼梯,普通链表一步一个阶梯,但是跳跃表可以达到一步好多个阶梯。所以效率比普通链表快多了。 

 

跳跃表实现需要两个类:一个节点类和一个跳跃表本身的类。

  =代码如果出错,欢迎指出=

节点类代码:

public class SkipNode

{

public int key;

public Object value;

public SkipNode[] link;

public SkipNode(int level,int key , Object Value)

{
this.key=key;

this.value=value;

link=new SkipNode[level];

}

 

跳跃表类代码:

public class SkipList

{

private int maxLevel;

private int level;

private SkipNode header;

private const int NIL=Int32.MaxValue;

private const int PROB =0.5F;

}

 

SkipList类的构造器包含两个部分:带单独一个参数的Public构造器,其中此参数是跳跃表内节点的总数量,以及一个完成大部分工作的Private构造器数。

 

 代码如下:

public SkipList(long maxNodes)         //把节点总数量传递给构造器方法作为方法内的唯一参数。初始化跳跃表对象工作的,private构造器在调用时会有两个参数

{                                                                                                    
this.SkipList2(PROB,(int)(Math.Ceiling(Math.Log(maxNodes)/Math.Log(1/PROB)-1)));  

}          

                                                                                                                                 

private void SkipList2(float probable,int maxLevel)   //设置了数据成员的数值,创建了跳跃表的头节点,创建了用于每个节点链的“空”节点,记忆初始化了该元素的链   

{
this.proability=probable;

this.maxLevel=maxLevel;

level=0;

header=new SkipNode(maxLevel,0,null);

SkipNode nilElement=new Skip(maxLevel,NIL,null);

  for(int i=0;i<=maxLevel-1;i++)

  
header.link[i]=nilElement;

}

 

概率方法代码:

private int GenRandomLevel()                 //随机给链层数

{

int newLevel=0;

Random r= new Random();

int ran=r.Next(0);

while((newLevel<maxLevel)&&ran<provavility))

     newLevel++;

return newLevel;

}

 

插入代码:

 

public void insert(int key,Object value)

{
SkipNode[] update=new SkipNode[maxLevel];

SkipNode cursor=header;

for( int i=level;i>=level;i--)            //从当前最高层到最底层

    {

 while (cursor.link[i].key<key)            //如果比要找的这个数值要小的话,就到指向下一个节点,用update【i】来接收每一层的最后一个节点

     cursor=cursor.link[i];

update[i]=cursor;

    }

cursor=cursor.link[0];

if (cursor.key=key)                          //如果存在,那就覆盖

  
cursor.value=value;

else

 {

int newLevel =GenRandomLevel();

   if (newLevel>level)                       //如果随机出来的链层比当前链层高的情况

     {

   for(int i=level+1;i<=newLevel-1;i++)

update[i]=header;

level=newLevel;

      }

cursor = new SkipNode(newLevel,key,Value);            // 插入

   for(int i=0;i<=newLevel-1;i++)           //插入后改变自己的链指向的节点,和前面节点的链指向的节点变成自己

    {

cursor.link[i]=update[i].link[i];

update[i].link[i]=cursor;

     }

  }

}

 

删除代码:

public void Delete(int key)

{

SkipNode[] update=new SkipNode[maxLevel+1];

SkipNode cursor=header;

for(Int i=level;i>=level;i--)                        

  {

   while(cursor.link[i].key<key)

cursor=cursor.link[i];

update[i]=cursor;

  }

cursor=cursor.link[0];

if(cursor.key==key)

  {

for(int i=0;i<level-1;i++)

  if(update[i].link[i]==cursor)

update[i].link[i]=cursor.link[i];                 //直接等于要删除节点的后面节点

while((level>0)&&(header.link[level].key==NIL))             //删除当前节点的链层

   level--;

  }

}

 

遍历代码:

public Object Search(int key)

{

SkipNode cursor=header;

for(int i=level;i>0;i--)

 {

SkipNode nexeElement=cursor.link[i];

while(nextElement.key<key)

{

cursor=nextElement;

nextElement=cursor.link[i];

}

}

cursor=cursor.link[0];

if(cursor.key==key)

  return cursor.value;

else

  return "Object not found";

}

跳跃表 C#的更多相关文章

  1. 跳跃表Skip List的原理和实现

    >>二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果 ...

  2. 浅析SkipList跳跃表原理及代码实现

    本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈“跳跃表”的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代 ...

  3. skip跳跃表的实现

    skiplist介绍 跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义, 跳表是由William Pugh发明的, ...

  4. 跳跃表Skip List【附java实现】

    skip list的原理 Java中的LinkedList是一种常见的链表结构,这种结构支持O(1)的随机插入及随机删除, 但它的查找复杂度比较糟糕,为O(n). 假如我们有一个有序链表如下,如果我们 ...

  5. skip list跳跃表实现

    跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义,跳表是由William Pugh发明的,这位确实是个大牛,搞出一 ...

  6. redis skiplist (跳跃表)

    redis skiplist (跳跃表) 概述 redis skiplist 是有序的, 按照分值大小排序 节点中存储多个指向其他节点的指针 结构 zskiplist 结构 // 跳跃表 typede ...

  7. 数据结构与算法(c++)——跳跃表(skip list)

    今天要介绍一个这样的数据结构: 单向链接 有序保存 支持添加.删除和检索操作 链表的元素查询接近线性时间 ——跳跃表 Skip List 一.普通链表 对于普通链接来说,越靠前的节点检索的时间花费越低 ...

  8. 基于跳跃表的 ConcurrentSkipListMap 内部实现(Java 8)

    我们知道 HashMap 是一种键值对形式的数据存储容器,但是它有一个缺点是,元素内部无序.由于它内部根据键的 hash 值取模表容量来得到元素的存储位置,所以整体上说 HashMap 是无序的一种容 ...

  9. redis 系列7 数据结构之跳跃表

    一.概述 跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的.在大部分情况下,跳跃表的效率可以和平衡树(关系型数据库的索引就是平衡树 ...

随机推荐

  1. Echarts动态数据显示

    自己慢慢摸索出来的,留着以后可能会用到 一.先引入jquery,再引入echarts.js 二.配置容器 三.配置路径和数据选项等 <script type="text/javascr ...

  2. 用户"IIS APPPOOL\xxxxxxxx"登录失败解决方案

    Server Error in '/' Application.-------------------------------------------------------------------- ...

  3. c#之process类相关整理

    一.根据进程名获取进程的用户名?   需要添加对 System.Management.dll 的引用   using System.Diagnostics; using System.Manageme ...

  4. 初识ege图形库

    简介: EGE (Easy Graphics Engine),是Windows 下的简易绘图库, 是一个类似BGI (graphics.h)的 面向C/C++语言新手的图形库,对新手来说,简单,友好, ...

  5. Redis与Scrapy

    Redis与Scrapy Redis与Scrapy Redis is an open source, BSD licensed, advanced key-value cache and store. ...

  6. javascript中可处理的浮点数的最高精度(和小数的一些小特性)

    1.之前在度娘那找了一下关于javascript中可处理的浮点数的最高精度的问题,但找了好久也找不到,于是自己 小小的研究了一下,之前以为是17,后来测到18,再后来又测到19,经过一系列的改写,得到 ...

  7. flask 后台表单验证模块

    我不想直接用flask的wtf模块,太大,功能太多,用不了.但后台也不能不做验证吧,我比较懒,不想一行一行写代码验证,所以就写了一个验证模块,对于小项目也够用了 # encoding=utf-8 # ...

  8. MySQL应用层传输协议分析

    001.在MySQL应用层传输协议中主要有如下三种类型的数据: 01.整数类型. 02.字符串类型. 03.描述数据包. 002.MySQL应用层传输协议中对整型的说明: 01.固定长度的整型---- ...

  9. Git学习04 --分支管理

    每次commit,Git都把它们串成一条时间线,这条时间线就是一个分支.截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支.HEAD严格来说不是指向提交,而是指向master ...

  10. Callable,Runnable比较及用法

    http://blog.csdn.net/xtwolf008/article/details/7713580 http://www.cnblogs.com/whgw/archive/2011/09/2 ...