Treap的读书笔记2
近期開始了自己高级数据结构之旅,在这次旅行中。我将持续把一些高级的数据结构从理论到编码都过一遍,同一时候通过博客形式分享出来。希望大家指出不足之处!
二叉排序树是一种动态排序的数据结构。支持插入、删除、查找等操作。且平均时间复杂度为O(log(N)),可是普通二叉排序树不能保证树退化为一颗分支的情况,此时最坏情况下的时间复杂度为O(N)。
此时,平衡二叉树的产生了。平衡二叉树是一种动态调整平衡的数据结构,但理想的平衡二叉树非常难,于是人们使用AVL、红黑树、Treap、伸展树等来替代平衡二叉树,这些数据结构能够非常好地改善最坏情况。但实现起来并非非常easy的事。
Treap是Heap+Tree,通俗来讲就是堆与树的结合,每一个节点除了keywordkey以及节点之间的连接关系外,还要保存一个优先级priority,注意这里的优先级不同于其它节点的随机数字,随机才干较好的期望平衡度,保证能够非常好维护二叉树的性质。当中在Treap中keywordkey遵循二叉查找树的性质,即:
(1)、空树是一颗二叉查找树。
(2)、若左子树不为空,则左子树中的所有keyword均小于该节点keyword;
(3)、若右子树不为空,则右子树中的所有keyword均不小于该节点keyword。
(4)、若左右子树非空。则左右子树也是一颗二叉查找树。
Treap中的优先级priority遵循Heap的性质,此处的堆已不再是棵全然二叉树,而是用指针取代数组下标实现的树结构,满足全部根节点优先级小于(或大于)左右孩子节点的优先级(在左右孩子存在的情况下,小于为小顶堆,大于为大顶堆)。
因为每一个节点上的优先级是随机产生的,所以期望高度能够达到非常好的程度。
在算法导论的12.4节中,其证明了随机构造的二叉查找树的期望高度为O(lgn)。因而treap的期望高度亦是O(lgn)。
Treap支持二叉树的全部操作,且平摊时间复杂度为O(log(N)),便于实现,性能好,克服了二叉查找树最坏情况时间复杂度为O(N)的弊端,有不存在AVL、红黑树等编码和理解难度,与伸展树有类似优点。
以下简要谈谈Treap的几种基本操作。
左旋:
右旋:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGoyNDE5MTc0NTU0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
以上截图来自http://www.cnblogs.com/huangxincheng/archive/2012/07/30/2614484.html。在此表示感谢!
查找:
查找直接用二叉树的性质,參考源码。
插入:
先找到插入位置,在运行插入操作,然后维护堆的性质,即依据优先级调整以维护小顶堆或大顶堆的性质。关于维护队的性质,參考我前面的关于对的博客。
删除:
类比二叉查找树一样,删除结点存在三种情况:
(1)、叶子结点,跟二叉查找树一样,直接释放本节点就可以。
(2)、仅仅有一个还自己节点,跟二叉查找树一样操作。
(3)、有两个孩子节点,能够像二叉查找树一样转换为删除右子树最小节点或左子树最大节点,然后将仅仅赋值到本应删除的节点处,此时能够一起复制优先级,然后向该分支调整,也可不赋值优先级保留原来的优先级,我的程序保留原来优先级。
更新:
先删除原节点,然后插入新节点。
因为期望高度为O(log(N))。所以以上全部操作的平潭时间复杂度为O(log(N))。
代码:
之前写了个带父亲指针的。感觉有点复杂,于是写了以下这段代码。查看带父亲指针的代码点击此处,感觉那个封装的比較好。
- #include<iostream>
- #include<ctime>
- using namespace std;
- class Treap
- {
- private:
- int num,key,pri;
- Treap *child[2];
- public:
- int compare(int);
- Treap(int);
- Treap* rotate(Treap*,int);
- Treap* erase(Treap*,int);
- Treap* leafNode();
- bool find(int);
- void setNum();
- Treap* insert(Treap*,int);
- void rotatePrint(Treap*,int);
- };
- Treap::Treap(int tKey)
- {
- num=0;
- key=tKey;
- pri=rand()%1000;
- child[0]=child[1]=NULL;
- }
- int Treap::compare(int tKey)
- {
- return key<tKey?1:0;
- }
- void Treap::setNum()
- {
- num=1;
- if(child[0]!=NULL)
- num+=child[0]->num;
- if(child[1]!=NULL)
- num+=child[1]->num;
- }
- Treap*Treap::rotate(Treap* tRoot,int dir)
- {
- Treap* ch=tRoot->child[dir];
- tRoot->child[dir]=ch->child[dir^1];
- ch->child[dir^1]=tRoot;
- tRoot->setNum();
- ch->setNum();
- return ch;
- }
- Treap* Treap::insert(Treap *tRoot,int tKey)
- {
- if(NULL==tRoot)
- return new Treap(tKey);
- int dir=this->compare(tKey);
- tRoot->child[dir]=tRoot->child[dir]->insert(tRoot->child[dir],tKey);
- if(tRoot->pri>tRoot->child[dir]->pri)
- tRoot=rotate(tRoot,dir);
- else tRoot->setNum();
- return tRoot;
- }
- Treap* Treap::leafNode()
- {
- if(NULL==child[0]&&NULL==child[1])
- {
- delete this;
- return NULL;
- }
- else if(NULL==child[0])
- {
- Treap *p=this->child[1];
- delete this;
- return p;
- }
- else if(NULL==child[1])
- {
- Treap *p=this->child[0];
- delete this;
- return p;
- }
- }
- Treap* Treap::erase(Treap* tRoot,int tKey)
- {
- if(NULL==tRoot)
- return NULL;
- if(key==tKey)
- {
- if(child[0]==NULL||child[1]==NULL)
- return leafNode();
- Treap *q=this,*p=this->child[1];
- bool left=false;
- while(p->child[0]!=NULL)
- {
- left=true;
- q=p;
- p=p->child[0];
- }
- this->key=p->key;
- if(!left)
- q->child[1]=p->leafNode();
- else q->child[0]=p->leafNode();
- return this;
- }
- int dir=this->compare(tKey);
- tRoot->child[dir]=tRoot->child[dir]->erase(tRoot->child[dir],tKey);
- return tRoot;
- }
- bool Treap::find(int tKey)
- {
- if(NULL==this)
- return false;
- if(key==tKey)
- return true;
- int dir=this->compare(tKey);
- return child[dir]->find(tKey);
- }
- void Treap::rotatePrint(Treap* tRoot,int dep)
- {
- if(NULL==tRoot)
- return ;
- rotatePrint(tRoot->child[0],dep+1);
- for(int i=0;i<dep;i++)
- cout<<" ";
- cout<<"("<<tRoot->key<<"。"<<tRoot->pri<<")"<<endl;
- rotatePrint(tRoot->child[1],dep+1);
- }
- void menu()
- {
- //Treap *root=new Treap(10);
- Treap *root=NULL;
- srand(unsigned(clock()));
- int val,choice;
- while(true)
- {
- cout<<"***************菜单*************"<<endl;
- cout<<" 1.插入"<<endl;
- cout<<" 2.删除"<<endl;
- cout<<" 3.查找"<<endl;
- cout<<" 4.退出"<<endl;
- cout<<"您的选择:[ ]\b\b\b";
- cin>>choice;
- cout<<"请输入数:";
- cin>>val;
- if(1==choice)
- root=root->insert(root,val);
- else if(2==choice)
- root=root->erase(root,val);
- else if(3==choice)
- {
- if(root->find(val))
- cout<<"查找成功!"<<endl;
- else cout<<"查找失败!"<<endl;
- }
- else if(4==choice)
- exit(0);
- cout<<"==================="<<endl;
- root->rotatePrint(root,0);
- }
- }
- int main()
- {
- while(true)
- menu();
- }
Treap的读书笔记2的更多相关文章
- 读书笔记汇总 - SQL必知必会(第4版)
本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...
- 读书笔记--SQL必知必会18--视图
读书笔记--SQL必知必会18--视图 18.1 视图 视图是虚拟的表,只包含使用时动态检索数据的查询. 也就是说作为视图,它不包含任何列和数据,包含的是一个查询. 18.1.1 为什么使用视图 重用 ...
- 《C#本质论》读书笔记(18)多线程处理
.NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Li ...
- C#温故知新:《C#图解教程》读书笔记系列
一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...
- C#刨根究底:《你必须知道的.NET》读书笔记系列
一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...
- Web高级征程:《大型网站技术架构》读书笔记系列
一.此书到底何方神圣? <大型网站技术架构:核心原理与案例分析>通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计 ...
- LOMA280保险原理读书笔记
LOMA是国际金融保险管理学院(Life Office Management Association)的英文简称.国际金融保险管理学院是一个保险和金融服务机构的国际组织,它的创建目的是为了促进信息交流 ...
- 《3D Math Primer for Graphics and Game Development》读书笔记2
<3D Math Primer for Graphics and Game Development>读书笔记2 上一篇得到了"矩阵等价于变换后的基向量"这一结论. 本篇 ...
- 《3D Math Primer for Graphics and Game Development》读书笔记1
<3D Math Primer for Graphics and Game Development>读书笔记1 本文是<3D Math Primer for Graphics and ...
随机推荐
- js中Date对象
Date常用的几个方法: var oDate=new Date(); oDate.getHours()方法是获取当前的小时 oDate.getMinutes()方法获取当前的分钟 oDate.getS ...
- Sliding Window Maximum
(http://leetcode.com/2011/01/sliding-window-maximum.html) A long array A[] is given to you. There is ...
- Android应用开发基础篇(7)-----BroadcastReceiver
链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/22/2363644.html 一.概述 BroadcastReceiver,意思就是广播信息接收 ...
- 记录:sea.js和require.js配置 与 性能对比
最近有点忙,很久无写博客,记录一下之前的配置require.js和sea.js的配置.(有误有望提出 require.js 文件目录 /app(项目使用js) /lib(require.js jq存放 ...
- spss
编辑 SPSS(Statistical Product and Service Solutions),“统计产品与服务解决方案”软件.最初软件全称为“社会科学统计软件包” (SolutionsStat ...
- C语言数组内存初始化
内存初始化当然有必然,但是不用memset,直接这样写就可以了:char* szRemoteFile = new char[MAX_LENGTH](); http://blog.csdn.net/pa ...
- 如何禁止scrollView 的子控件自动滑到 底部或者中间部分
现象:当一个scrollView 里面包含很多childView,并且整个界面超出屏幕的范围,而且每个childView都获取焦点,scrollView就会自动滑到底部或者中间部分. 可以使用以下几种 ...
- cocos2d-x中的尺寸之二
接下来我们再做些坏事,比如给EGLView设置分辨率,代码如下: pEGLView->setDesignResolutionSize(240, 320, kResolutionExactFit) ...
- c语言编写经验逐步积累4
寥寥数笔,记录我的C语言盲点笔记,仅仅为以前经历过,亦有误,可交流. 1.逻辑表达式的使用 取值 = 表达式 ? 表达式1:表达式2: 比方x = y > z ? y:z 2."+,- ...
- ASP.net体系