【数据结构】跳跃链表(Skip list)
来源:互联网 发布:股票数据接口插件 编辑:程序博客网 时间:2024/05/16 11:12
普通的链表存在一个严重的缺陷:
需要顺序扫描才能找到所需要的元素。而且查找从链表的开头开始,只有找到了所需要的元素,或者直到链表的末尾都没有找到这个元素时才会停下来。将量表进行排序可以加速查找的过程,但是仍然需要顺序查找。因此,很容易想到,链表最好可以跳过某些节点,以避免顺序处理。
从而,引出了跳跃链表,跳跃链表是有序链表的一个有趣的变种,可以进行非顺序查找。
在有n个节点的跳跃链表中,对于每个满足1≦k≦└ lgn ┘ 和 1≦└ n/2^(k-1)┘-1 的k和i,位于2^(k-1)·i的结点指向位于2^(k-1)·(i+1)的节点。这意味着第二个节点指向前面距离两个单位的节点,第四个节点指向前面距离4个单位的节点,以此类推。所以,要在链表的结点中包含不同树木的指针:半数节点只有一个指针,1/4的节点有两个指针,1/8节点有3个指针,一次列退。可以看出,指针数表明了每个节点的级,而级的数量为maxLevel = └ lg n ┘+1
为了查找元素e1,应该从最高层上的指针开始,找到该元素就成功地结束查找。如果到达该链表的末尾,或者遇到大雨元素e1的某个元素key,就包含key的那个节点的前一个节点重新开始查找,但是这次查找是从比前面低一级的指针开始。知道找到e1,或者沿着第一级的指针到达了链表的末尾,或者找到一个大于e1的元素,查找才会停止。下面给出为代码:
search(元素e1)p = 最高层i上的非空链表;while 没有找到 e1 且 i ≥ 0if p-> key < e1p = 从 --i级上p的前驱开始的子链表;else if p->key > e1if p是i级上的最后一个节点p = 在 <i的最高级上从p开始的非空子链表i = 新的级数else p = p-> next
下面是跳表的具体实现:
//// Created by 大幕 on 2017/9/13.//#ifndef SKIPLIST_SKIPLIST_H#define SKIPLIST_SKIPLIST_H#include <iostream>const int DefaultSize = 100;template <typename E,typename K>struct SkipNode{ E data; //数据域 SkipNode<E,K> **link; //指针数组域 SkipNode(int size = DefaultSize){ //构造函数 link = new SkipNode<E,K> *[size]; if(link = nullptr) { std::cerr <<"存储分配失败!"<<std::endl; exit(1); } } ~SkipNode() { delete []link; }};/** * 跳表类定义 * 其中large是一个比字典中任何一个元素的值都大的值 * 放在尾结点中。0级链上的元素值从左向右按照升序进行排列 * 但是不包括附加头结点 */template <typename E,typename K>class SkipList{public: SkipList(K large,int maxLev = DefaultSize); //构造函数 ~SkipList(); bool Search(const K k1,E& e1)const; //搜索函数 E& getData(SkipNode<E,K> *current) { if(current != nullptr) return current->data; else return nullptr; } bool Insert(const K k1,E &e1); //插入函数 bool Remove(const K k1,E &e1); //删除函数private: int maxLevel; //所允许的最大级数 int Levels; K TailKey; SkipNode<E,K> *head; //附加头结点 SkipNode<E,K> *tail; //附加尾结点 SkipNode<E,K> **last; //指针数组 int level(); SkipNode<E,K> *SaveSearch(const K k1);};/***跳表的构造函数初始化Level(当前出现的最大级别)、maxLevel、TailKey(所有元素值均小于这个值) * 还为附加头结点和尾结点分配空间。在插入和删除之前进行搜索时, * 所遇到的每条链上的最后一个元素均被放在数组last中。附加头结点中有maxLevel+1个用于指向 * 各级链的指针被初始化为指向尾结点(空链表). * 析构函数释放链表中用到的所有空间 *//** * 跳表的构造函数和析构函数 */template <typename E,typename K>SkipList<E,K>::SkipList(K large, int maxLev) { //构造函数,建立空的多级链 maxLevel = maxLev; //最大级链数目 TailKey = large; //控制扫描的最大关键码 Levels = 0; head = new SkipNode<E,K>(maxLevel+1); //附加头结点,有maxLevel+1个指针 tail = new SkipNode<E,K>(0); //附加尾结点,有0个指针 last = new SkipNode<E,K> *[maxLevel+!]; //跳表的多级链的头指针 tail -> data = large; for(int i =0;i<maxLevel;i++) { head->link[i] = tail; }}template<typename E,typename K>SkipList<E,K>::~SkipList() { /** * 析构函数,释放链表上的所有元素节点 */ SkipNode<E,K> *next; while(head != tail) { next = head->link[0]; delete head; head = next; } delete tail; delete []last;}/** * 跳表的搜索。插入和删除 *//** * 1.跳表的搜索: * 跳表有两个搜索函数,当需要搜索一个值为k1的元素时,可用公共成员函数Search * 如果找到想要搜索的元素,则将这个元素返回到e1中,并返回true,否则返回false. * Search从最飞机链(Level级,仅含有一个元素)的表头开始搜索,顺着指针向右搜索 * 逐步逼近要搜索的元素,一直走到0级链。 * 当从for循环退出时,正好处于要寻找的元素的左边。与0级链的下一个元素进行比较, * 就能知道要找的元素是否在跳表中 * * 第二个搜索函数是私有函数SaveSearch(),作用是由插入和删除进行调用, * SaveSearch不仅仅包含了Search的全部功能,而且可以把每一级中遇到的最后一个结点存放到数组last中FFFFFF */template <typename E,typename K>bool SkipList<E,K>::Search(const K k1, E &e1) const { if(k1 > TailKey) return false; SkipNode<E,K> *p = head; for(int i = Levels;i >= 0;i--) //逐级向下搜索 { while(p->link[i]->data < k1) //重载,元素关键码判小于 p = p->link[i]; } e1 = p->link[0]->data; return e1 == k1; //重载,元素关键码判等于}template <typename E,typename K>SkipNode<E,K>* SkipList<E,K>::SaveSearch(const K k1) { if(k1 > TailKey) return nullptr; SkipNode<E,K> *p = head; for(int i = Levels; i >= 0; i--) { while (p->link[i]->data < k1) p = p->link[i]; last[i] = p; //记下最后比较的及诶单 } return p->link[0];}#endif //SKIPLIST_SKIPLIST_H
阅读全文
0 0
- 【数据结构】跳跃链表(Skip list)
- Skip List跳跃链表
- Skip List(跳跃表)
- 跳跃表Skip List
- 跳跃表 Skip List
- 数据结构之六(跳跃表Skip List)
- 跳跃表(Skip List)
- 跳跃表(Skip List)
- skip list跳跃表实现
- LevelDB中的Skip List(跳跃表)
- Skip List跳跃表代码实现
- 跳跃表(skip list) 的实现
- 跳跃表(Skip List)深入介绍
- 跳跃表(Skip List)深入介绍
- LevelDB中的Skip List(跳跃表)
- 跳跃表(Skip List)-实现(Java)
- 跳跃表(Skip List)-实现(Java)
- 跳跃表(Skip List)-实现(Java)
- Apache Common Id
- MySql从一窍不通到入门(二)大数据量分页查询方法
- Centos7解决中文乱码问题
- 写了好久越来越多错了!!!!发下我的源代码牛牛们帮看一下
- 第2周 【项目一】 利用函数实现传值
- 【数据结构】跳跃链表(Skip list)
- sublime安装步骤
- opencv人体识别技术汇总
- jQuery图片延迟加载(懒加载)之 jquery.lazyload.js
- Qt unicode
- 图像处理 面试准备
- MongoDb数据库学习基础语法(一)
- 牛客网-剑指offer-08-跳台阶
- 在递归终止条件前进行了一些操作,导致程序bug