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 ...
随机推荐
- UVa1584 Circular Sequence
#include <stdio.h>#include <string.h> int less(char* str, size_t len, size_t p, size_t q ...
- linux下安卓编译apk环境搭建
ubuntu下linux安卓编译环境搭建. 配置好编译环境 (前提是已经安装了jdk,可以用java -verison 命令查看) 一.设置环境变量 用vi ~/.bashrc 打开编译环境 JA ...
- USACO Section 5.4 TeleCowmunication(最小割)
挺裸的一道最小割.把每台电脑拆成一条容量为1的边,然后就跑最大流.从小到大枚举每台电脑,假如去掉后 最大流=之前最大流+1,那这台电脑就是answer之一了. -------------------- ...
- mysql 本机root密码忘记
1.找到对应的my.conf,在mysqld节点添加:skip-grant-tables 2.重启mysql 即可无密登录 3.update user表中的密码后,去除skip-grant-tabl ...
- React使用笔记(3)-React Event Listener
Date: 2015-11-28 12:18 Category: Web Tags: JavaScript Author: 刘理想 [toc] 1. 构造基本结构 首先,我们先创建一个按钮,一个输入框 ...
- java 显示视频时间--玩的
1.显示视频时间 package view.time; import it.sauronsoftware.jave.Encoder; import it.sauronsoftware.jave.Mul ...
- C语言实现约瑟夫环讨论
[问题描述] 约瑟夫(Joseph)问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数).一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针 ...
- Nginx工作原理和优化、漏洞(转)
查看安装了哪些模块命令: [root@RG-PowerCache-X xcache]# nginx/sbin/nginx -Vnginx version: nginx/1.2.3built by gc ...
- MySQL对于有大量重复数据表的处理方法
需要在MySQL的一张innodb引擎的表(tableA)上添加一个唯一索引(idx_col1_u).但是对于每个key(col1)表中已经有大量重复数据.此时,做数据的手工清理,或者SQL处理是非常 ...
- android天气查询(一)websevice之ksoap2软件包的使用
对于用到天气信息,首先我想: 第一:数据不可能是我测得的,必须是网上的信息. 第二:网上的信息分为好多种,具体哪种比较好一点,这里我总结了两种. 第三:数据JSON怎么解析. 第四:如何提出数据与显示 ...