这是一篇两年前写的东西,自我感觉还是相当不错的Treap教程。正好期末信息科学技术概论课要求交一个论文,就把这个东西修改了一下交了,顺便也发到这里吧。

随机平衡二叉查找树Treap的分析与应用

1、序

详细实现了二叉查找树的各种操作:插入结点、构造二叉树、删除结点、查找、  查找最大值、查找最小值、查找指定结点的前驱和后继

2、二叉查找树简介

它或者是一棵空树;或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; (3)左、右子树也分别为二叉排序树

3、二叉查找树的各种操作

此处给出代码,注释非常详细,具体操作请参考代码:

  1. /*************************************************************************
  2. 这是一个二叉查找树,实现了以下操作:插入结点、构造二叉树、删除结点、查找、
  3. 查找最大值、查找最小值、查找指定结点的前驱和后继。上述所有操作时间复杂度
  4. 均为o(h),其中h是树的高度
  5. 注释很详细,具体内容就看代码吧
  6. *************************************************************************/
  7. #include<stdio.h>
  8. #include<stdlib.h>
  9. //二叉查找树结点描述
  10. typedef int KeyType;
  11. typedef struct Node
  12. {
  13. KeyType key;          //关键字
  14. struct Node * left;   //左孩子指针
  15. struct Node * right;  //右孩子指针
  16. struct Node * parent; //指向父节点指针
  17. }Node,*PNode;
  18. //往二叉查找树中插入结点
  19. //插入的话,可能要改变根结点的地址,所以传的是二级指针
  20. void inseart(PNode * root,KeyType key)
  21. {
  22. //初始化插入结点
  23. PNode p=(PNode)malloc(sizeof(Node));
  24. p->key=key;
  25. p->left=p->right=p->parent=NULL;
  26. //空树时,直接作为根结点
  27. if((*root)==NULL){
  28. *root=p;
  29. return;
  30. }
  31. //插入到当前结点(*root)的左孩子
  32. if((*root)->left == NULL && (*root)->key > key){
  33. p->parent=(*root);
  34. (*root)->left=p;
  35. return;
  36. }
  37. //插入到当前结点(*root)的右孩子
  38. if((*root)->right == NULL && (*root)->key < key){
  39. p->parent=(*root);
  40. (*root)->right=p;
  41. return;
  42. }
  43. if((*root)->key > key)
  44. inseart(&(*root)->left,key);
  45. else if((*root)->key < key)
  46. inseart(&(*root)->right,key);
  47. else
  48. return;
  49. }
  50. //查找元素,找到返回关键字的结点指针,没找到返回NULL
  51. PNode search(PNode root,KeyType key)
  52. {
  53. if(root == NULL)
  54. return NULL;
  55. if(key > root->key) //查找右子树
  56. return search(root->right,key);
  57. else if(key < root->key) //查找左子树
  58. return search(root->left,key);
  59. else
  60. return root;
  61. }
  62. //查找最小关键字,空树时返回NULL
  63. PNode searchMin(PNode root)
  64. {
  65. if(root == NULL)
  66. return NULL;
  67. if(root->left == NULL)
  68. return root;
  69. else  //一直往左孩子找,直到没有左孩子的结点
  70. return searchMin(root->left);
  71. }
  72. //查找最大关键字,空树时返回NULL
  73. PNode searchMax(PNode root)
  74. {
  75. if(root == NULL)
  76. return NULL;
  77. if(root->right == NULL)
  78. return root;
  79. else  //一直往右孩子找,直到没有右孩子的结点
  80. return searchMax(root->right);
  81. }
  82. //查找某个结点的前驱
  83. PNode searchPredecessor(PNode p)
  84. {
  85. //空树
  86. if(p==NULL)
  87. return p;
  88. //有左子树、左子树中最大的那个
  89. if(p->left)
  90. return searchMax(p->left);
  91. //无左子树,查找某个结点的右子树遍历完了
  92. else{
  93. if(p->parent == NULL)
  94. return NULL;
  95. //向上寻找前驱
  96. while(p){
  97. if(p->parent->right == p)
  98. break;
  99. p=p->parent;
  100. }
  101. return p->parent;
  102. }
  103. }
  104. //查找某个结点的后继
  105. PNode searchSuccessor(PNode p)
  106. {
  107. //空树
  108. if(p==NULL)
  109. return p;
  110. //有右子树、右子树中最小的那个
  111. if(p->right)
  112. return searchMin(p->right);
  113. //无右子树,查找某个结点的左子树遍历完了
  114. else{
  115. if(p->parent == NULL)
  116. return NULL;
  117. //向上寻找后继
  118. while(p){
  119. if(p->parent->left == p)
  120. break;
  121. p=p->parent;
  122. }
  123. return p->parent;
  124. }
  125. }
  126. //根据关键字删除某个结点,删除成功返回1,否则返回0
  127. //如果把根结点删掉,那么要改变根结点的地址,所以传二级指针
  128. int deleteNode(PNode* root,KeyType key)
  129. {
  130. PNode q;
  131. //查找到要删除的结点
  132. PNode p=search(*root,key);
  133. KeyType temp;    //暂存后继结点的值
  134. //没查到此关键字
  135. if(!p)
  136. return 0;
  137. //1.被删结点是叶子结点,直接删除
  138. if(p->left == NULL && p->right == NULL){
  139. //只有一个元素,删完之后变成一颗空树
  140. if(p->parent == NULL){
  141. free(p);
  142. (*root)=NULL;
  143. }else{
  144. //删除的结点是父节点的左孩子
  145. if(p->parent->left == p)
  146. p->parent->left=NULL;
  147. else  //删除的结点是父节点的右孩子
  148. p->parent->right=NULL;
  149. free(p);
  150. }
  151. }
  152. //2.被删结点只有左子树
  153. else if(p->left && !(p->right)){
  154. p->left->parent=p->parent;
  155. //如果删除是父结点,要改变父节点指针
  156. if(p->parent == NULL)
  157. *root=p->left;
  158. //删除的结点是父节点的左孩子
  159. else if(p->parent->left == p)
  160. p->parent->left=p->left;
  161. else //删除的结点是父节点的右孩子
  162. p->parent->right=p->left;
  163. free(p);
  164. }
  165. //3.被删结点只有右孩子
  166. else if(p->right && !(p->left)){
  167. p->right->parent=p->parent;
  168. //如果删除是父结点,要改变父节点指针
  169. if(p->parent == NULL)
  170. *root=p->right;
  171. //删除的结点是父节点的左孩子
  172. else if(p->parent->left == p)
  173. p->parent->left=p->right;
  174. else //删除的结点是父节点的右孩子
  175. p->parent->right=p->right;
  176. free(p);
  177. }
  178. //4.被删除的结点既有左孩子,又有右孩子
  179. //该结点的后继结点肯定无左子树(参考上面查找后继结点函数)
  180. //删掉后继结点,后继结点的值代替该结点
  181. else{
  182. //找到要删除结点的后继
  183. q=searchSuccessor(p);
  184. temp=q->key;
  185. //删除后继结点
  186. deleteNode(root,q->key);
  187. p->key=temp;
  188. }
  189. return 1;
  190. }
  191. //创建一棵二叉查找树
  192. void create(PNode* root,KeyType *keyArray,int length)
  193. {
  194. int i;
  195. //逐个结点插入二叉树中
  196. for(i=0;i<length;i++)
  197. inseart(root,keyArray[i]);
  198. }
  199. int main(void)
  200. {
  201. int i;
  202. PNode root=NULL;
  203. KeyType nodeArray[11]={15,6,18,3,7,17,20,2,4,13,9};
  204. create(&root,nodeArray,11);
  205. for(i=0;i<2;i++)
  206. deleteNode(&root,nodeArray[i]);
  207. printf("%d\n",searchPredecessor(root)->key);
  208. printf("%d\n",searchSuccessor(root)->key);
  209. printf("%d\n",searchMin(root)->key);
  210. printf("%d\n",searchMax(root)->key);
  211. printf("%d\n",search(root,13)->key);
  212. return 0;
  213. }

4、附录

参考书籍     《算法导论》

二叉查找树(二叉排序树)的详细实现,以及随机平衡二叉查找树Treap的分析与应用的更多相关文章

  1. 【查找结构3】平衡二叉查找树 [AVL]

    在上一个专题中,我们在谈论二叉查找树的效率的时候.不同结构的二叉查找树,查找效率有很大的不同(单支树结构的查找效率退化成了顺序查找).如何解决这个问题呢?关键在于如何最大限度的减小树的深度.正是基于这 ...

  2. 平衡二叉查找树 AVL 的实现

    不同结构的二叉查找树,查找效率有很大的不同(单支树结构的查找效率退化成了顺序查找).如何解决这个问题呢?关键在于如何最大限度的减小树的深度.正是基于这个想法,平衡二叉树出现了. 平衡二叉树的定义 (A ...

  3. 006-数据结构-树形结构-二叉树、二叉查找树、平衡二叉查找树-AVL树

    一.概述 树其实就是不包含回路的连通无向图.树其实是范畴更广的图的特例. 树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合. 1.1.树的特性: 每个结点有零个或多个子 ...

  4. 平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板【超详解】

    平衡树初阶——AVL平衡二叉查找树 一.什么是二叉树 1. 什么是树. 计算机科学里面的树本质是一个树状图.树首先是一个有向无环图,由根节点指向子结点.但是不严格的说,我们也研究无向树.所谓无向树就是 ...

  5. 数据结构-自平衡二叉查找树(AVL)详解

    介绍: 在计算机科学中,AVL树是最先发明的自平衡二叉查找树. 在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树. 查找.插入和删除在平均和最坏情况下都是O(log n).增 ...

  6. AVL树(平衡二叉查找树)

    首先要说AVL树,我们就必须先说二叉查找树,先介绍二叉查找树的一些特性,然后我们再来说平衡树的一些特性,结合这些特性,然后来介绍AVL树. 一.二叉查找树 1.二叉树查找树的相关特征定义 二叉树查找树 ...

  7. 算法学习 - 平衡二叉查找树实现(AVL树)

    平衡二叉查找树 平衡二叉查找树是非常早出现的平衡树,由于全部子树的高度差不超过1,所以操作平均为O(logN). 平衡二叉查找树和BS树非常像,插入和删除操作也基本一样.可是每一个节点多了一个高度的信 ...

  8. 二叉查找树、平衡二叉树(AVLTree)、平衡多路查找树(B-Tree),B+树

    B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引. B+树中的B代表平衡(balance),而不是二叉(binary),因为B+树是从最早的平衡二叉树演化而来的. 在 ...

  9. 深入浅出数据结构C语言版(12)——平衡二叉查找树之AVL树

    在上一篇博文中我们提到了,如果对普通二叉查找树进行随机的插入.删除,很可能导致树的严重不平衡 所以这一次,我们就来介绍一种最老的.可以实现左右子树"平衡效果"的树(或者说算法),即 ...

随机推荐

  1. JavaScript实现ajax发送表单数据

    知识点: 1.重置表单数据 2.获取表单数据(纯JavaScript) 3.设置表单数据(纯JavaScript) 4.ajax发送数据到客户端 (1)设置请求头,自己组合数据 (2)实例化表单对象, ...

  2. Spark记录-Scala shell命令

    1.scala shell命令 scala> :help All commands can be abbreviated, e.g., :he instead of :help. :edit & ...

  3. CM记录-HDFS清理垃圾回收站

    HDFS数据块所在存储的目录满了的解决方法 1.增加磁盘空间 2.删除回收站 hadoop dfs -du -h 查看各个HDFS空间占用情况 hadoop dfs  -expunge  清空回收站 ...

  4. JIRA项目管理搭建

    部署JIRA 7.2.2 for Linux 转自:http://www.yfshare.vip/2017/05/09/%E9%83%A8%E7%BD%B2JIRA-7-2-2-for-Linux/ ...

  5. Nginx配置项优化(转载)

    (1)nginx运行工作进程个数,一般设置cpu的核心或者核心数x2 如果不了解cpu的核数,可以top命令之后按1看出来,也可以查看/proc/cpuinfo文件 grep ^processor / ...

  6. 关于 xcode5 的no matching provisioning profiles found

    CHENYILONG Blog 关于 xcode5 的no matching provisioning prof- about the question in xcode5 "no matc ...

  7. redis初使用

    下载地址:https://redis.io/download Redis项目不正式支持Windows.但是,微软开放技术小组开发并维护了针对Win64的Windows端口 windows版下载地址:h ...

  8. Oracle 基本操作符

    1.一般操作符 (1)!= 不等于 select empno,ename,job from scott.emp where job!='manager' (2)^= 不等于 select empno, ...

  9. Java练习之使用StringBuilder

    package string.demo; /* * 将数组变为字符串输出 */ public class StringBuilderTest { /** * @param args */ public ...

  10. 基于Consul的数据库高可用架构【转】

    几个月没有更新博客了,已经长草了,特意来除草.本次主要分享如何利用consul来实现redis以及mysql的高可用.以前的公司mysql是单机单实例,高可用MHA加vip就能搞定,新公司mysql是 ...