当前位置: 首页 > 编程日记 > 正文

[转载]二叉树(BST,AVT,RBT)

二叉查找树(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++实现:

二叉树之BST、AVL和RBT

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实现

二叉树之BST、AVL和RBT

2.右单旋转(rotate right):

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

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

二叉树之BST、AVL和RBT

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的左儿子(上述过程完成右旋转)。

二叉树之BST、AVL和RBT

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

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

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

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

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

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

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

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

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

性质2. 根是黑色

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

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

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

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

二叉树之BST、AVL和RBT

插入:红黑树结点的插入与二叉查找树基本一样,不一样的是红黑树把新插入的结点标记为红色,如果新插入的结点的父节点也为红色,那么就按照下面三种情况,做出调整,以维护红黑树的性质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做一次右旋转。

二叉树之BST、AVL和RBT

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

二叉树之BST、AVL和RBT

删除:红黑树结点的删除与二叉查找树基本一样,不一样的是如果删除的结点是黑色,则破坏了红黑树的性质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做一次做旋转,调整到此完毕。

二叉树之BST、AVL和RBT

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

二叉树之BST、AVL和RBT

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

相关文章:

Invalid Host header 问题解决

出现该问的原因&#xff1a; 因为新版的 webpack-dev-server 出于安全考虑&#xff0c;默认检查 hostname&#xff0c;如果hostname不是配置内的就不能访问。 解决办法&#xff1a;设置跳过host检查 打开你的项目全局搜索 devServer &#xff0c;在 devServer 里面添加 &quo…

react hooks使用_为什么要使用React Hooks?

react hooks使用The first thing you should do whenever youre about to learn something new is ask yourself two questions -每当您要学习新东西时&#xff0c;应该做的第一件事就是问自己两个问题- Why does this thing exist? 为什么这东西存在&#xff1f; What probl…

算法 - 字符串匹配

http://blog.csdn.net/linhuanmars/article/details/20276833 转载于:https://www.cnblogs.com/qlky/p/7817471.html

工作流入门链接

百度百科-工作流 http://baike.baidu.com/link?urlZjElBNByyZz_ItLtd_Uqt3Sadcwv0-4CDO806vKQWJDuUOFybbkzpg8GOB1EU71w8bT4x64RoRXBrFXa7o_dK 企业应用工作流的好处http://jingyan.baidu.com/article/90895e0fe9c56164ec6b0b24.html工作流管理的好处http://blog.sina.com.cn/…

uniapph5配置index.html模板路径不生效解决办法

很简单&#xff0c;关闭应用再重新启动试试&#xff0c;还不行的话&#xff0c;重启IDE

终端软件升级功能开发_5个很棒的终端技巧可帮助您升级为开发人员

终端软件升级功能开发There are plenty of beginner tutorials around that help you learn command line basics, such as cd, ls, pwd and so on...but what about that fancy magic youve seen more experienced developers use?周围有很多初学者教程可以帮助您学习命令行基…

自定义左右侧滑菜单

实现效果&#xff1a; 左右侧滑菜单&#xff0c;侧滑栏占主屏比为60%监听触控&#xff0c;自定义滑动动画&#xff0c;当侧边栏滑动超过50%松开触控将自动滑动到60%&#xff0c;未超过50%松开触控回归侧边栏隐藏为主屏设置蒙版效果&#xff0c;根据侧滑菜单的占屏比设置主屏蒙版…

uniapp设置模板路径页面样式混乱解决办法

乱了就在html里面加上下面这行代码试试 <link rel"stylesheet" href"<% BASE_URL %>static/index.css" /> <meta name"viewport" content"widthdevice-width, initial-scale1.0, user-scalableno, minimum-scale1.0, maxim…

JavaScript获取当前日期,昨天,今天日期以及任意天数间隔日期

<script language"JavaScript" type"text/javascript"> function GetDateStr(AddDayCount) { var dd new Date(); dd.setDate(dd.getDate()AddDayCount);//获取AddDayCount天后的日期 var y dd.getYear(); var m dd.getMonth()1;//获取当前月份…

snapd_snapd使管理Nextcloud变得轻而易举

snapdAs I’ve described in both my Linux in Action book and Linux in Motion course, Nextcloud is a powerful way to build a file sharing and collaboration service using only open source software running on your own secure infrastructure. It’s DropBox, Skyp…

atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty  HttpListener...

atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty HttpListener 1. 自定义web服务器的实现方案&#xff0c;基于原始socket vs 基于tcpListener vs 基于HttpListener1 2. download1 3. Lib3 4. Code3 5. HttpListener类4 6. Reef5 1. 自定义web服务器…

Python高级函数--map/reduce

名字开头大写 后面小写&#xff1b;练习&#xff1a; 1 def normalize(name): 2 return name[0].upper() name[1:].lower() 3 L1 [adam, LISA, barT] 4 L2 list(map(normalize, L1)) 5 print(L2) reduce求积&#xff1a; 1 from functools import reduce 2 3 def prod(…

样式集(9) - 切换Tab菜单

先上效果图 下面是以vue实现的示例代码&#xff1a; 代码解析&#xff1a; 很简单的代码&#xff0c;直接复制粘贴使用吧~ 别忘记一键三连哦&#xff0c;点赞&#xff0c;收藏&#xff0c;关注&#xff0c;谢谢~ 后续持续更新更多干货哦&#xff01;&#xff01; <temp…

python字典{:4}_Python字典101:详细的视觉介绍

python字典{&#xff1a;>4}欢迎 (Welcome) In this article, you will learn how to work with Python dictionaries, an incredibly helpful built-in data type that you will definitely use in your projects.在本文中&#xff0c;您将学习如何使用Python字典&#xff…

asp.net提交危险字符处理方法之一

在form表单提交前&#xff0c;可以在web页面&#xff0c;submit按钮的click事件中&#xff0c;使用js函数对&#xff0c;可能有危险字符的内容进行编码。 有3个函数可用&#xff1a; encodeURI() 函数可把字符串作为 URI 进行编码。 escape() 函数可对字符串进行编码&#xff0…

mysql帐号,权限管理

-> use mysql; //选择数据库 -> select host,user,password from user; //查询已有用户 -> insert into user (host,user,password) values(localhost,kiscms,password(kiscms)); //插入一个用户 -> select host,user,password from user; //再次查询用户 -> fl…

样式集(10) - 滑动删除功能实现,VUE完整源码附效果图

先看效果图 实现方式&#xff1a; 使用 scroll-view 标签&#xff0c;进行横向滑动&#xff0c;达到左滑出现删除按钮&#xff0c; 注&#xff1a;如果不是使用uni-app或者小程序框架&#xff0c;没有 scroll-view 组件的话可以通过CSS实现哦 下面看uni-app的实现代码&#…

机器学习关键的几门课程_互联网上每门机器学习课程,均按您的评论排名

机器学习关键的几门课程by David Venturi大卫文图里(David Venturi) 互联网上每门机器学习课程&#xff0c;均按您的评论排名 (Every single Machine Learning course on the internet, ranked by your reviews) A year and a half ago, I dropped out of one of the best com…

[POJ2104]K-th Number(区间第k值 记录初始状态)

题目链接&#xff1a;http://poj.org/problem?id2104 给n个数和m个查询&#xff0c;查询[i, j]内第k小的数是多少。&#xff08;主席树、划分树那种高大上的姿势叒不会啊QAQ 可以在维护这n个数的同时维护刚刚输入的时候他们的下标&#xff0c;之后预处理排序一次&#xff0c;查…

Geant4采用make和cmake编译运行geant4自带例子的方法

该教程介绍如何将geant4中自带的例子通过camke编译成可执行文件&#xff0c;并运行程序。 1 在linux主目录下创建一个geant4_workdir目录&#xff0c;并将geant4自带的例子B1复制到该目录下&#xff0c;如图1所示&#xff0c;geant4自带的B1源文件所在目录为geant4安装目录&…

GitLab设置中文

第一步&#xff0c;点击右上角的头像 点击Preferences&#xff0c;选择语言 选择简体中文然后保存

java python算法_用Python,Java和C ++示例解释的排序算法

java python算法什么是排序算法&#xff1f; (What is a Sorting Algorithm?) Sorting algorithms are a set of instructions that take an array or list as an input and arrange the items into a particular order.排序算法是一组指令&#xff0c;这些指令采用数组或列表…

c++运算符重载总结

c的一大特性就是重载(overload)&#xff0c;通过重载可以把功能相似的几个函数合为一个&#xff0c;使得程序更加简洁、高效。在c中不止函数可以重载&#xff0c;运算符也可以重载。由于一般数据类型间的运算符没有重载的必要&#xff0c;所以运算符重载主要是面向对象之间的。…

一道面试题:js返回函数, 函数名后带多个括号的用法及join()的注意事项

博客搬迁&#xff0c;给你带来的不便&#xff0c;敬请谅解&#xff01; http://www.suanliutudousi.com/2017/11/13/js%E8%BF%94%E5%9B%9E%E5%87%BD%E6%95%B0%E4%B8%AD%EF%BC%8C%E5%87%BD%E6%95%B0%E5%90%8D%E5%90%8E%E5%B8%A6%E5%A4%9A%E4%B8%AA%E6%8B%AC%E5%8F%B7%E7%9A%84%E…

小程序画布画海报保存成图片可以保存实现完整代码

老规矩先来个效果图&#xff1a; 因为是截图所以会有些模糊&#xff0c;在真机上会比较清晰 下面针对效果图来看看里面都画了什么元素&#xff0c;代码在文章的最后&#xff0c;大家想直接拷代码可以略过这&#xff0c;这里是方便大家理解代码。 首先&#xff0c;咱们的海报有…

fcm和firebase_我如何最终使Netlify Functions,Firebase和GraphQL一起工作

fcm和firebaseIn a previous post I confessed defeat in attempting to get an AWS Lambda GraphQL server to connect to a Firebase server. I didn’t give up right away, though, and a short time later found a different Node package to achieve what I couldn’t be…

深入了解Mvc路由系统

请求一个MVC页面的处理过程 1.浏览器发送一个Home/Index 的链接请求到iis。iis发现时一个asp.net处理程序。则调用asp.net_isapi 扩展程序发送asp.net框架 2.在asp.net的第七个管道事件中会遍历UrlRoutingModule中RouteCollection的RoteBase集合 通过调用其GetRouteData方法进行…

uni-app h5页面左上角出现“取消“字眼解决办法

在项目根目录的index.html中加上一行代码 <link rel"stylesheet" href"<% BASE_URL %>static/index.<% VUE_APP_INDEX_CSS_HASH %>.css" /> 如图&#xff1a;

unity编辑器扩展_01(在工具栏中创建一个按钮)

代码&#xff1a; [MenuItem("Tools/Test",false,1)] static void Test() { Debug.Log("test"); } 注意&#xff1a;MenuItem中第一个参数:需要创建选项在工具栏中的路径&#xff0c;此路径的父目录可以是Unity中已存在的&#xff0c;也…

postgres语法_SQL Create Table解释了MySQL和Postgres的语法示例

postgres语法A table is a group of data stored in a database.表是存储在数据库中的一组数据。 To create a table in a database you use the CREATE TABLE statement. You give a name to the table and a list of columns with its datatypes.要在数据库中创建表&#…