Python3实现红黑树[上篇]
Python3实现红黑树[上篇]
由于时间有限,这次只写了红黑树添加节点,关于节点的删除放在下一讲 https://blog.csdn.net/qq_18138105/article/details/105324025。
关于红黑树的介绍,来由,性质和定义,可以看这篇文章,本篇就不再赘述了:红黑树,超强动静图详解,简单易懂
关于红黑树,其实比较容易摸不着头脑的是“左旋”和“右旋”。
既然是旋转,那么肯定有支点和旋点,也就是以支点为轴,旋点绕支点 顺时针 或 逆时针旋转。
那么,“左旋” 和 “右旋” 到底哪个是顺时针,哪个是逆时针呢?
在这里,旋点一定是支点的父节点,也就是说旋点的位置比支点高,因此 左旋就是逆时针旋转,右旋就是顺时针旋转!
对于旋转,分享一个口诀:
右旋: 支点占旋点原位,支点的右给旋点作为左,旋点作为支点的右,交换支点和旋点的颜色
左旋: 支点占旋点原位,支点的左给旋点作为右,旋点作为支点的左,交换支点和旋点的颜色
先借用大神的2个图。如下图所示,就是 以p为支点,g右旋的过程,看看是否符合上面的口诀呢: 经过右旋后,支点p占据旋点g的原位,支点p的右T3作为了旋点g的左,旋点g作为了p的右。
再看看左旋:经过左旋后,支点p占据旋点g的原位,支点p的左T3作为了旋点g的右,旋点g作为了p的左。也是符合上面的口诀的。
以下便是python3代码实现 红黑树插入节点的过程。
# 红黑树节点
class RBN(object):def __init__(self, data):self.data = data # 数据域self.color = 0 # 0红 1黑self.left = Noneself.right = Noneself.parent = None# 红黑树
class RBT(object):def __init__(self):self.root = None# 中序遍历def midTraverse(self, x):if x == None:returnself.midTraverse(x.left)colorStr = '黑' if x.color == 1 else '红'parentStr = '父=' + ('nil' if x.parent == None else str(x.parent.data))print(x.data, colorStr, parentStr)self.midTraverse(x.right)# 添加一个节点def add(self, x):# 如果没有根节点 作为根节点if self.root == None:self.root = xx.color = 1 # 根节点为黑色# print('添加成功', x.data)return# 寻找合适的插入位置p = self.rootwhile p != None:if x.data < p.data:if p.left == None:p.left = xx.parent = p# print('添加成功', x.data)self.addFix(x)breakp = p.leftelif x.data > p.data:if p.right == None:p.right = xx.parent = p# print('添加成功', x.data)self.addFix(x)breakp = p.rightelse:return# 调整红黑树def addFix(self, x):while True:if x == self.root: # 如果处理到根节点了 则着色为黑x.color = 1returnp = x.parent # 爸爸if p.color == 1 or x.color == 1: # 自己和爸爸只要有一个是黑的 就构不成双红 则返回return# 接下来分析红爸爸情况g = p.parent # 爷爷 红爸爸肯定有爸爸,因为红色绝不是根节点u = g.left if p == g.right else g.right # 叔叔 叔叔可能为空节点if u != None and u.color == 0: # 红叔叔 则着色 然后从爷爷开始向上继续调整u.color = p.color = 1 # 叔叔和爸爸都变黑色g.color = 0 # 爷爷变红色x = g # x指向爷爷,然后继续循环continue# 接下来分析黑叔叔得情况 有四种情况 左左,左右,右左,右右if p == g.left and x == p.left: # 左左# 以爸爸为支点右旋爷爷self.rotateRight(p)elif p == g.left and x == p.right: # 左右# 以x为支点左旋爸爸self.rotateLeft(x)# 以x为支点右旋爷爷(上面的旋转把爷爷变成了新爸爸)self.rotateRight(x)elif p == g.right and x == p.right: # 右右 其实就是 左左的镜像# 以爸爸为支点左旋爷爷self.rotateLeft(p)elif p == g.right and x == p.left: # 右左 其实就是 左右的镜像# 以x为支点右旋爸爸self.rotateRight(x)# 以x为支点左旋爷爷(上面的旋转把爷爷变成了新爸爸)self.rotateLeft(x)## 关于红黑树的旋转,一直是个难搞的点# 这里我提供一个口诀:# 右旋: 支点占旋点原位,支点的右给旋点作为左,旋点作为支点的右# 左旋: 支点占旋点原位,支点的左给旋点作为右,旋点作为支点的左## 右旋 p支点def rotateRight(self, p):g = p.parent # 支点的父节点就是旋点# 右旋gif g == self.root: # 若g是根节点 则p升为根节点self.root = pp.parent = Noneelse: # 若g不是根节点 那么必然存在g.parent p占据g的位置gp = g.parentp.parent = gpif g == gp.left:gp.left = pelse:gp.right = pg.left = p.rightif p.right != None:p.right.parent = gp.right = gg.parent = p# g和p颜色交换p.color, g.color = g.color, p.color# 左旋 p 支点def rotateLeft(self, p):g = p.parent # 支点的父节点就是旋点# 左旋gif g == self.root: # 若g是根节点 则p升为根节点self.root = pp.parent = Noneelse: # 若g不是根节点 那么必然存在g.parent p占据g的位置gp = g.parentp.parent = gpif g == gp.left:gp.left = pelse:gp.right = pg.right = p.leftif p.left != None:p.left.parent = gp.left = gg.parent = p# g和p颜色交换p.color, g.color = g.color, p.colorif __name__ == '__main__':rbt = RBT()datas = [10, 20, 30, 15]# datas = [11, 2, 14, 1, 7, 15, 5, 8, 4]for x in datas:rbt.add(RBN(x))rbt.midTraverse(rbt.root)
关于红黑树节点的删除,请看下回分解。
Python3实现红黑树[上篇]相关推荐
- Python3实现红黑树[下篇]
Python3实现红黑树[下篇] 我写的红黑树的上篇在这里:https://blog.csdn.net/qq_18138105/article/details/105190887 这是我近期看的文章 ...
- 红黑树的插入与验证——附图详解
文章目录 红黑树 性质 红黑树的插入 前言 寻找插入位置 情况 1.0 情况 1.1 情况 1.2 情况 1.3 情况 2.0 情况 2.1 情况 2.2 情况 2.3 完整代码 红黑树的检验 验证代 ...
- 浅谈树形结构的特性和应用(上):多叉树,红黑树,堆,Trie树,B树,B+树......
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 上篇文章我们主要介绍了线性数据结构,本篇233酱带大家看看 无所不 ...
- 面试旧敌之红黑树(直白介绍深入理解)
2019独角兽企业重金招聘Python工程师标准>>> 读完本文你将了解到: 什么是红黑树 黑色高度 红黑树的 5 个特性 红黑树的左旋右旋 指定节点 x 的左旋 右图转成左图 指定 ...
- 彻底理解面试难点之rb-tree(红黑树)续--对红黑树的插入和删除操作的一些理解!!!
这里主要讲一下对红黑树的插入和删除操作的一些理解 对于红黑树的一些相关性质的介绍,上篇已经讲了,这里不再介绍,有需要了解的,可以翻前面的博客看看. 1.红黑树的插入操作 对于红黑树的元素插入,我们首先 ...
- pygraphviz的安装与红黑树可视化
大家好,我是小小明,今天我将带大家安装pygraphviz,并通过它对红黑树这种数据结构进行可视化. pygraphviz的安装与红黑树的可视化 安装graphviz 下载地址:http://www. ...
- 图解:什么是红黑树?(下篇)
点击关注上方"五分钟学算法", 设为"置顶或星标",第一时间送达干货. 转自景禹 说到红黑树的删除操作,不得不提 图解:什么是红黑树?(中篇)中所讲的红黑树的插 ...
- 红黑树 键值_大厂面试官:说一下JDK1.8 HashMap有哪些亮点?
上篇我们介绍了JDK1.7版的HashMap,今天我们来讲解下JDK1.8版的HashMap. JDK1.7的实现大家看出有没有需要优化的地方? 其实一个很明显的地方就是:当 Hash 冲突严重时,在 ...
- Java 集合深入理解(17):HashMap 在 JDK 1.8 后新增的红黑树结构
点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 上篇文章我们介绍了 HashMap 的主要特点和关键方法源码解读,这篇文章我们介绍 HashMap 在 JDK1.8 新增 ...
最新文章
- C编程,随机数,排序
- 二叉树题目----6 二叉树的最近公共祖先 AND 二叉树搜索树转换成排序双向链表
- ASIHttpRequest:创建队列、下载请求、断点续传、解压缩
- CMD执行命令出现NOMALY: meaningless REX prefix used以及IDEA提示Cannot run git问题解决
- Java 时间处理 Instant
- java 字节乱码_Android/Java 字节读取出现乱码问题
- IOS--CALayer实现,界限、透明度、位置、旋转、缩放组合动画(转)
- 【干货】GRU神经网络
- clipse和IDEA快捷键对照表
- Ambari 安装配置 MySql
- 【数学建模】CUMCM-2009B 眼科病床的合理安排 解题思路整理
- JAVA毕设项目民航售票管理系统(java+VUE+Mybatis+Maven+Mysql)
- sqlite设密工具如何使用(本人资源)
- 从四大造字法看文字所承载的文化_举例说明汉语汉字所承载的文化信息?
- python中安装decimal模块_python decimal和fractions模块
- 绿色债券数据集2016.01-2021.11年
- 将 vim 外的内容复制并粘贴到 Vim 里使用,如从windows系统复制内容到vim中使用
- 大概是全网最详细的Electron ipc 讲解(二)——渲染进程与渲染进程的搭桥牵线
- .Net C# 如何读取Excel数据内容写入数据库并通过DataGridView控件动态刷新显示
- 汇编语言程序设计IV-贺利坚-专题视频课程