近期開始了自己高级数据结构之旅,在这次旅行中。我将持续把一些高级的数据结构从理论到编码都过一遍,同一时候通过博客形式分享出来。希望大家指出不足之处!

二叉排序树是一种动态排序的数据结构。支持插入、删除、查找等操作。且平均时间复杂度为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的更多相关文章

  1. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  2. 读书笔记--SQL必知必会18--视图

    读书笔记--SQL必知必会18--视图 18.1 视图 视图是虚拟的表,只包含使用时动态检索数据的查询. 也就是说作为视图,它不包含任何列和数据,包含的是一个查询. 18.1.1 为什么使用视图 重用 ...

  3. 《C#本质论》读书笔记(18)多线程处理

    .NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Li ...

  4. C#温故知新:《C#图解教程》读书笔记系列

    一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...

  5. C#刨根究底:《你必须知道的.NET》读书笔记系列

    一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...

  6. Web高级征程:《大型网站技术架构》读书笔记系列

    一.此书到底何方神圣? <大型网站技术架构:核心原理与案例分析>通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计 ...

  7. LOMA280保险原理读书笔记

    LOMA是国际金融保险管理学院(Life Office Management Association)的英文简称.国际金融保险管理学院是一个保险和金融服务机构的国际组织,它的创建目的是为了促进信息交流 ...

  8. 《3D Math Primer for Graphics and Game Development》读书笔记2

    <3D Math Primer for Graphics and Game Development>读书笔记2 上一篇得到了"矩阵等价于变换后的基向量"这一结论. 本篇 ...

  9. 《3D Math Primer for Graphics and Game Development》读书笔记1

    <3D Math Primer for Graphics and Game Development>读书笔记1 本文是<3D Math Primer for Graphics and ...

随机推荐

  1. BootStrap 智能表单系列 五 表单依赖插件处理

    这一章比较简单哦,主要就是生产表单元素后的一些后续处理操作,比如日期插件的渲染.一些autocomplete的处理等,在回调里面处理就可以了, demo: $("input.date-pic ...

  2. 3. 表单输入框 在 IE 中 会有 “X” 和 类似wifi图标的图标出现

    原因: IE 自动给 input加了伪类 ::ms-clear 和 ::ms-reveal 解决: input::ms-clear, input::ms-reveal { display: none; ...

  3. spring MVC中文乱码相关总结

    总结几种方式,都使用的话能解决大多数乱码的情况 1.所有页面使用 <%@page language="java" pageEncoding="UTF-8" ...

  4. Assertion failure in -[UIView layoutSublayersOfLayer:]

    Assertion failure in -[UIView layoutSublayersOfLayer:], /SourceCache/UIKit/UIKit-2935.137/UIView.m:8 ...

  5. iOS实践04

    第四天 微博数据展示:获取服务器数据,json数据的解析,MVC的使用,自定义cell高度的计算,一些分类的设计.已经是第四天了,虽然每天都有课程,但这个东西也基本完成了一大半吧,一些忘掉的知识也捡起 ...

  6. IS-A 和 HAS-A

    IS-A关系 IS-A就是说:一个对象是另一个对象的一个分类. 下面是使用关键字extends实现继承. public class Animal{ } public class Mammal exte ...

  7. 帝国cms分页样式修改文件-注意事项

    帝国cms分页样式主要有:内容页分页样式.列表页分页样式以及默认搜索模板使用的搜索样式等几种. 要改这些样式其实也很简单,在网站目录中找到相应的.css文件修改empages属性就行了,但是这样比较麻 ...

  8. JS中的内存泄漏

    明天下午面试微店的前端开发职位,有点紧张~~ 刚刚正好看到js中的内存泄露,所以来整理一番. 给DOM对象添加的属性是对一个js对象的引用. var MyObject = {}; document.g ...

  9. 一张图解释---Java多态

    1.向上转型:编译器自动进行,不需要声明 Snowboard s = new Snowboard (); Object o = s; (相当于指向Snowboard的内部Object实例,所有类都继承 ...

  10. (IOS)悬浮按钮Demo

    思路:传入一个底层的view,将悬浮按钮(用view实现)和展开的子按钮列表add在其上,子按钮列表开始将坐标和悬浮按钮对应好后先将其隐藏,悬浮按钮识别到tap手势后触发展示子按钮列表的方法.通过在t ...