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

二叉排序树是一种动态排序的数据结构。支持插入、删除、查找等操作。且平均时间复杂度为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. zoj 1109 zoj 1109 Language of FatMouse(字典树)

    好开心,手动自己按照字典树的思想用c写了一个优化后的trie字典树,就是用链表来代替26个大小的字符数组.完全按照自己按照自己的想法打的,没有参考如何被人的代码.调试了一天,居然最后错在一个小问题上, ...

  2. LeetCode Coins in a Line

    There are n coins in a line. Two players take turns to take one or two coins from right side until t ...

  3. JavaSE复习日记 : 八种基本数据类型

    /* * 基本数据类型 * * Java里的8种基本数据类型: * byte --- 1 byte = 8 bit; * short --- 2 byte = 16 bit; * int --- 4 ...

  4. Java 网络编程(一) 网络基础知识

    链接地址:http://www.cnblogs.com/mengdd/archive/2013/03/09/2951826.html 网络基础知识 网络编程的目的:直接或间接地通过网络协议与其他计算机 ...

  5. Hadoop学习笔记(2)hadoop框架解析

    Hadoop是适合大数据的分布式存储与计算平台 HDFS的架构:主从式结构 主节点只有一个NameNode,从节点可以有很多个DataNode. NameNode负责: (1)接收用户操作请求 (2) ...

  6. Git merge local repository

    I've met this problem for so many times and let me write a blog for solving this problem. First, you ...

  7. DOM Traversal Example | Documentation | Qt Project

    DOM Traversal Example | Documentation | Qt Project DOM Traversal Example

  8. ExpandableListView(二)替换箭头图标被拉伸的问题

    之前写过一篇替换系统默认图标的文章,之后又发现了问题,当替换成自己的图片之后,图片被拉伸了!为了解决这个问题,我几乎尝试了所有方法,结果都不理想 我试过的方法,在布局里,把textview上的内容字体 ...

  9. Cocos2d-x C++调用Android弹出提示框

    转载请注明地址,谢谢.. Cocos2d-x中提供了一个JniHelper类来让我们对Jni进行操作. (PS:弄了一天想自己写代码操作Jni的,但是总是出错,技术差不得不使用Cocos2d-x现成的 ...

  10. Node.mysql

    mysql为常用数据库,下面简单记录在nodejs中操作mysql数据库的简单实现. 环境: nodejs4.2.2 mysql5.7.12 win7 参考资料: npm mysql 代码 var m ...