二叉查找树(Binary Search Tree)是满足如下性质的二叉树:①若它的左子树非空,则左子树上所有结点的值均小于根结点的值;②若它的右子树非空,则右子树上所有结点的值均大于根结点的值;③左、右子树本身又各是一棵二叉查找树。

通俗的讲,二叉查找树的左子树上的结点不比父结点大,右子树上的结点不比父结点小,即,设x为二叉查找树中的一个结点,如果y是x的左子树中的一个结点,则key[y]<=key[x];如果y是x的右子树中的一个结点,则key[x]<=key[y]。此处的key[x],key[y]表示的是x结点和y结点的关键字。

1.最小关键字元素:要查找二叉查找树中具有最小关键字的元素,只要从根节点开始,沿着各节点的left指针查找下去,直到遇到NULL为止。查找最大关键字元素情况类似。

TREE-MINIMUM (x)

1 while left[x] ≠ NULL

2   do x ← left[x]

3 return x

2.后继:如果所有的关键字均不相同,则某一结点x的后继即是具有大于key[X]中的关键字中最小者的那个结点。查找结点X的后继包含两种情况(1)如果结点X的右子树非空,结点X的后继即是右子树中具有最小关键字的结点。(2)如果结点x的右子树为空,且假设结点X的后继为Y,则Y是X的最低祖先结点,且Y的左孩子是X的祖先。前驱的情况类似。

TREE-SUCCESSOR(x)

1 if right[x] ≠ NULL

2   then return TREE-MINIMUM (right[x])

3 yp[x]

4 while y ≠ NULL and x = right[y]

5   do xy

6   yp[y]

7 return y

下面是后继的C++实现:

3.插入:根据二叉查找树的性质,我们先将要插入的元素跟根元素,如果大于根结点的key,则插入到其右子树中,如果小于根结点的key值,则插入到其左子树中。

4.删除:将给定结点Z从二叉查找树中删除的过程是以指向Z的指针作为参数。删除步骤分为三种:

(1)如果Z没有子女,则修改其父节点P[Z],使NULL为其子女,替换Z。

(2)如果结点只有一个孩子,则通过在其子节点与父节点之间建立一条链来删除Z。

(3)最后若Z有两个子女,先删除Z的后继Y(后继Y没有左孩子,注意这时真正删除的是结点Y),再用Y的内容替换Z的内容。

TREE-DELETE(T, z)

1 if left[z] = NULL or right[z] = NULL

2   then yz

3 else y ← TREE-SUCCESSOR(z)

4 if left[y] ≠ NULL

5   then xleft[y]

6 else xright[y]

7 if x ≠ NULL

8   then p[x] ← p[y]

9 if p[y] = NULL

10   then root[T] ← x

11 else if y = left[p[y]]

12   then left[p[y]] ← x

13 else right[p[y]] ← x

14 if yz

15   then key[z] ← key[y]

16   copy y's satellite data into z

17 return y

=======================================  AVL树 ========================================

一棵AVL树是一棵平衡树,除了二叉查找树的性质外,还有这个性质:它的左子树和右子树都是AVL树,且左子树和右子树的高度之差的绝对值不超过1。这个性质保证了N个元素的AVL树的高度总为LogN,所以它查找的最坏复杂度仍然是LogN,所以说它是一种严格平衡的二叉查找树。

下面是一个Flash做的动态模拟AVL树上结点的插入与删除的过程,非常有趣,对了解AVL树也非常有用:http://www.qmatica.com/DataStructures/Trees/AVL/AVLTree.swf

如果在一棵原本是平衡的AVL树中插入一个新结点,造成了不平衡。此时必须调整树的结构,使之平衡化。平衡化旋转有两类:单旋转(左旋和右旋)和双旋转(左平衡和右平衡)。下面先依次介绍旋转的方法。

1.左单旋转(rotate left):

适用情况:见下图。在A的右孩子B的右子树C上插入结点,使得A结点的平衡因子从﹣1变成﹣2,需要对A进行一次左单旋转。(其中A平衡因子为left[A]->height - right[A]->height)

方法:以A的右孩子结点B为轴,节点A逆时针旋转,成为节点B的左儿子,节点B原左子树成为节点A的右子树。下面是左旋转的cpp实现

2.右单旋转(rotate right):

适用情况:在C的左孩子B的左子树A上插入结点,使得C结点的平衡因子从1变成2,需要对C进行一次右单旋转。

方法:以C的左孩子结点B为轴,节点C顺时针旋转,成为节点B的右儿子,节点B原右子树成为节点C的左子树

3. 先左后右双旋转(rotation left right

适用情况:见下图。在C的左孩子A的右子树B上插入结点,使得C结点的平衡因子从1变成2,需要对C进行先左后右双旋转。

方法:以C的左孩子A的右孩子B为轴,将节点A逆时针旋转,成为节点B的左儿子,现在C的左孩子为B(上述过程完成左旋转);以C的左孩子B为轴,将节点C顺时针旋转,成为节点B的右儿子(上述过程完成右旋转)。

4. 先右后左双旋转(rotation right left

适用情况:在A的右孩子C的左子树上B插入结点,使得A结点的平衡因子从-1变成-2,需要对A进行先右后左双旋转。

方法:以A的右孩子C的左孩子B为轴,将节点C顺时针旋转,成为节点B的右儿子,现在A的右孩子为B(上述过程完成左旋转);以A的右孩子B为轴,将节点A逆时针旋转,成为节点B的左儿子(上述过程完成右旋转)。

AVL树的插入操作与BST相同,插入后从插入结点到根节点从下到上依次检查该路径上各个结点的平衡度,按照四种情况,做出对应的旋转。

AVL树的删除操作:首先定位要删除的节点。

(1)如果该节点有左孩子,则用左子树的最大结点替换替换该节点,替换后递归删除左子树的最大结点;

(2)如果该节点没有左孩子有右孩子,则用右子树的最小结点替换替换该节点,替换后递归删除右子树的最小结点;

(3)如果该节点没有孩子,则删除该结点。

删除后从删除结点到根节点从下到上依次调整高度,该旋转的旋转。

======================================= 红黑树 ========================================

红黑树的定义也是它的性质,有以下五条:

性质1. 节点是红色或黑色

性质2. 根是黑色

性质3. 所有叶子都是黑色(叶子是NULL节点)

性质4. 如果一个节点是红的,则它的两个儿子都是黑的

性质5. 从任一节点到其叶子的所有简单路径都包含相同数目的黑色节点。

另外为了便于处理红黑树代码的边界条件,我们常常采用一个哨兵来代表NULL。哨兵是一个与树内普通结点具有相同域的对象。所有指向NULL的指针都替换成指向哨兵的指针。

插入:红黑树结点的插入与二叉查找树基本一样,不一样的是红黑树把新插入的结点标记为红色,如果新插入的结点的父节点也为红色,那么就按照下面三种情况,做出调整,以维护红黑树的性质4或是2。新插入的结点为N,N的叔叔结点为U。实际情况应该有六种,下面的三种情况中P都是G的左孩子,当P是G的右孩子时,处理方法类似,旋转的方向相反。

(1)N的叔叔U为红色:将N的父节点P[N]与U标记为黑色,将P[P[Z]]标记为红色,然后把P[P[Z]]当做新插入的结点,往上循环调整。

(2) N的叔叔U是黑色的,而且N是右孩子:将P[N]做一次左旋,使P[N]成为N的左孩子,并将旋转前的P[N]作为新插入的结点N。这样情况(2)就转化成了情况(3)。

(3) N的叔叔U是黑色的,而且N是左孩子:改变P与G的颜色,对G做一次右旋转。

下面是红黑树插入操作的C++实现(截图部分只有上面三种情况):

删除:红黑树结点的删除与二叉查找树基本一样,不一样的是如果删除的结点是黑色,则破坏了红黑树的性质5,需要调整,如果删除的结点是红色,那么就不需要调整。现在假设删除结点的孩子为N,如果N是红色的,那么直接将N调整成黑色就能维持红黑树的性质。否则的话,按下面的四种情况处理。实际情况应该有八种,下面的四种情况中N都是其父节点P的左孩子,当N是P的右孩子时,处理方法类似,旋转的方向相反。

(1)N的兄弟S是红色:改变P和S的颜色,对P进行一次左旋转,这样情况(1)就转换成了情况(2)、(3)、(4);

(2)N的兄弟S是黑色,而且S的两个孩子都是黑色:将S改成红色,将P为新的X循环处理;

(3) N的兄弟S是黑色,而且S的左孩子SL是红色,S的右孩子SR是黑色:改变SL与S的颜色,并对S进行一次右旋转,这样情况(3)就转化成了情况(4)

(4) N的兄弟S是黑色,而且S的右孩子SR是红色:改变P和S的颜色,并对P做一次做旋转,调整到此完毕。

红黑树删除结点操作的C++实现:

c++完整实现:

二叉查找树:http://www.oschina.net/code/snippet_176897_14148

AVL树:http://www.oschina.net/code/snippet_176897_14149

红黑树:http://www.oschina.net/code/snippet_176897_14155

转载于:https://www.cnblogs.com/wxquare/p/5211568.html

[转载]二叉树(BST,AVT,RBT)相关推荐

  1. 20170515_建立排序二叉树BST

    20170515_建立排序二叉树BST //108. Convert Sorted Array to Binary Search Tree //Given an array where element ...

  2. 排序二叉树BST(binary search/sort tree)

    之前介绍说,树这种存储结构,能提高数据的存储,读取效率.所以树的应用就可以体现在排序这一方面,比如有排序二叉树,平衡二叉树,红黑树等.本文介绍排序二叉树. 为啥有排序二叉树(二叉搜索树)的出现?这要从 ...

  3. [转载]二叉树先序、中序、后序三种遍历的非递归算法

    本贴给出二叉树先序.中序.后序三种遍历的非递归算法,此三个算法可视为标准算法. 1.先序遍历非递归算法 #define maxsize 100 typedef struct { Bitree Elem ...

  4. 转载 二叉树的创建、遍历、深度、叶子节点数

    1 # include <stdio.h> 2 # include <malloc.h> 3 typedef struct BiTNode{ 4 struct BiTNode ...

  5. 3. 数据结构--二叉树 BST AVL树 Huffman

    数据结构–二叉树 KEY:(不敢相信没有堆-) 二叉树的定义及其主要特征 ☑️ 二叉树的顺序存储结构和链式存储结构实现 二叉树的遍历及应用 二叉排序(查找.检索)树 (BST) 平衡的二叉检索树- A ...

  6. 算法 二叉树 BST树

    二叉排序树 BST树的定义 BST树结构 BST树的创建 递归中序遍历 非递归中序遍历 逆向非递归中序遍历 删除结点 BST树的定义 BST树又称为:二叉排序树,二叉搜索树 二叉搜索树或者是一颗空树, ...

  7. sdut 2128 树结构练习——排序二叉树(BST)的中序遍历

    树结构练习--排序二叉树的中序遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem Descript ...

  8. C++ struct结构体 实现搜索二叉树(BST)

    代码如下: #include <iostream> using namespace std;struct BSTNode {double v = 0.0;BSTNode *lc = nul ...

  9. C++ class类 实现搜索二叉树(BST)

    代码如下: #include <iostream> using namespace std;class BSTNode {private:double key;BSTNode *lchil ...

最新文章

  1. 武汉网络推广优化中网站关键词如何更合理布局分布?
  2. Socket编程(C语言实现)—— Nginx支持Socket转发
  3. 放在NSArray、NSDictionary等容器内的对象Item,Item中的property在程序运行过程中被无故释放...
  4. Android用户界面设计学习之旅-第二站
  5. 常用安卓开发技巧汇总
  6. C#发送电子邮件 (异步) z
  7. 无法安装 计算机缺失,还原安装程序Windows缺失的文件 - Windows Client | Microsoft Docs...
  8. 胆道取石内镜篮行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  9. Log4net PatternLayout 参数
  10. 强推WordPress里的一款代码高亮插件——EnlighterJS
  11. 彻底关闭win10自动更新
  12. 接受数据的php文件源码,PHP文件上传源码分析(RFC1867)
  13. SpringBoot开发常用技术这些你知道吗???
  14. 倾斜摄影超大场景的三维模型的顶层合并的优势浅析
  15. VB、VBA、VBS的区别你搞清楚了吗?
  16. 13 款开源全文检索引擎
  17. Bootstrap typeahead自动补全插件的坑
  18. java10_JAVA10 64位下载|java se development kit 10(JDK10)下载 v10.0 官方版 - 比克尔下载
  19. Python新型冠状病毒疫情数据自动爬取+统计+发送报告+数据屏幕(二)统计篇
  20. 关于版权声明的格式 (Copyright)

热门文章

  1. linux tar的使用方法
  2. A Strange Bitcoin Transaction
  3. 软件可读性和效率取舍_网络通信设计中的一些限制和取舍:摘要
  4. 1039 到底买不买
  5. 人工神经网络是如何实现存算一体的
  6. 2021年还适合参加软件测试培训吗
  7. 智能POS常见问题整理
  8. JavaScript学习记录 (三) 函数和对象
  9. thinkphp整合系列之gulp实现前端自动化
  10. 开发板tftp:timeout问题