数据结构--跳表SkipList
发布日期:2021-07-01 03:39:38
浏览次数:2
分类:技术文章
本文共 2869 字,大约阅读时间需要 9 分钟。
- 对单链表查找一个元素的时间复杂度是 O(n)
- 通过对链表建立多级索引的结构,就是跳表,查找任意数据、插入数据、删除数据的时间复杂度均为 O(log n)
- 前提:建立了索引,用空间换时间的思路
- (每两个节点建立一个索引)索引节点总和 n/2+n/4+n/8+…+8+4+2 = n-2,空间复杂度 O(n)
- 插入和删除后,动态更新索引,避免局部链表元素过多或者过少,退化成单链表 skiplist.h
/** * @description: 跳表 * @author: michael ming * @date: 2019/4/22 22:21 * @modified by: */#ifndef SKIPLIST_SKIPLIST_H#define SKIPLIST_SKIPLIST_H#include#include #include using namespace std;typedef unsigned int UINT;template class skipNode{ public: T data; skipNode **next; //跳表节点的next是 skipNode * 类型的数组 skipNode(const UINT level) { next = new skipNode * [level+1]; //索引级别从0(链表自身)开始 for(int i = 0; i < level+1; ++i) next[i] = NULL; } skipNode(const UINT level, const T& inputdata):data(inputdata) { next = new skipNode * [level+1]; //索引级别从0(链表自身)开始 for(int i = 0; i < level+1; ++i) next[i] = NULL; } ~skipNode () { delete [] next; }};template class skiplist{ private: UINT randomLevel() { // static bool flag = false;// if(!flag)// { // srand(UINT(time(0)));// flag = true;// }// else// flag = false; UINT lv = 0; for(int i = 0; i < maxLevel; ++i) { if(rand()%2) lv++; } return lv; }public: UINT maxLevel; skipNode *head; skiplist (UINT level = 10):maxLevel(level) { head = new skipNode (level); } ~skiplist () { skipNode *p = head, *q; while(p) { q = p; p = p->next[0]; delete q; } } void insert(const T& inputdata) { skipNode * newNode = new skipNode (maxLevel, inputdata); skipNode * temPos[maxLevel+1]; skipNode *p = head, *q = NULL; for(int i = maxLevel; i >= 0; i--) //记录插入点在每层的前一个位置 { while((q = p->next[i]) && (q->data <= inputdata)) { p = q; } temPos[i] = p; } UINT lv = randomLevel(); //新节点的随机索引级数 for(int i = 0; i <= lv; ++i) //将新节点依次连接进去 { newNode->next[i] = temPos[i]->next[i]; temPos[i]->next[i] = newNode; } } void delete_node(const T& inputdata) { skipNode * temPos[maxLevel+1]; skipNode *p = head, *q = NULL; for(int i = maxLevel; i >= 0; i--) { while((q = p->next[i]) && (q->data < inputdata)) { p = q; } temPos[i] = p; } if(q && q->data == inputdata) { for(int i = 0; i <= maxLevel; ++i) { if(temPos[i]->next[i] == q) temPos[i]->next[i] = q->next[i]; } delete q; q = NULL; } } void printSkipList() { skipNode *p, *q; for(int i = maxLevel; i >= 0; --i) { p = head; while(q = p->next[i]) { cout << q->data << " -> "; p = q; } cout << endl; } }};#endif //SKIPLIST_SKIPLIST_H
test_skiplist.cpp
/** * @description: 测试跳表 * @author: michael ming * @date: 2019/4/23 0:07 * @modified by: */#include "skiplist.h"int main(){ skiplist intSList; for(int i = 0; i < 10; ++i) { intSList.insert(i); } intSList.printSkipList(); intSList.delete_node(9); intSList.printSkipList(); intSList.delete_node(100); intSList.printSkipList(); return 0;}
以上写的比较简单,删除多个节点后,索引重新合理重建没有写。应该还有很多需要改进的地方,先放一放,往后继续学,保持学习进度。
测试结果:转载地址:https://michael.blog.csdn.net/article/details/89416539 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
网站不错 人气很旺了 加油
[***.192.178.218]2024年04月11日 23时17分55秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Mysql使用binlog恢复数据解决误操作问题的两种方法
2019-05-02
理解和配置Out of memory: Kill process
2019-05-02
MySQL binlog格式解析
2019-05-02
mysql优化——explain详解
2019-05-02
linux 下 pip 安装教程
2019-05-02
运维监控系统之Open-Falcon
2019-05-02
数据库对比:选择MariaDB还是MySQL?
2019-05-02
Mysqlbinlog工具及导出数据并转换编码导入
2019-05-02
使用Percona MySQL 5.7版本遇到的坑
2019-05-02
名词解释:Linux内存管理之RSS和VSZ
2019-05-02
547. 省份数量
2019-05-02
SpringMVC @RequestParam 中文乱码问题解决
2019-05-02
阿里云OSS 分块上传的代码整理
2019-05-02
前后端分离。前端POST请求参数过长,导致400错误解决办法及分析
2019-05-02
Spring MVC之@RequestBody, @ResponseBody 详解
2019-05-02
Mysql主从概述
2019-05-02
Mysql主从Java端实现
2019-05-02
PMM设置grafana登录用户
2019-05-02
为什么双主只建议单节点写入?
2019-05-02