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)

关于红黑树节点的删除,请看下回分解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337453.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

web应用程序并发测试_测试并发应用

web应用程序并发测试本文是我们名为Java Concurrency Essentials的学院课程的一部分。 在本课程中&#xff0c;您将深入探讨并发的魔力。 将向您介绍并发和并发代码的基础知识&#xff0c;并学习诸如原子性&#xff0c;同步和线程安全性的概念。 在这里查看 &#xff01; 目录…

深入理解存储器层次结构

点击蓝字关注我们1概述对于一个简单的计算机系统模型&#xff0c;我们可以将存储器系统看做是一个线性的字节数组&#xff0c;而 CPU 能够在一个常数时间内访问每个存储器的位置。实际上&#xff0c;存储器系统&#xff08;memory system&#xff09;是一个具有不同容量、成本和…

python中可选参数是什么意思_Python如何定义有可选参数的元类

问题 你想定义一个元类&#xff0c;允许类定义时提供可选参数&#xff0c;这样可以控制或配置类型的创建过程。 解决方案 在定义类的时候&#xff0c;Python允许我们使用 metaclass关键字参数来指定特定的元类。 例如使用抽象基类&#xff1a; from abc import ABCMeta, abstra…

C++的一个指针占内存几个字节?

C的一个指针占内存几个字节&#xff1f;结论&#xff1a; 取决于是64位编译模式还是32位编译模式&#xff08;注意&#xff0c;和机器位数没有直接关系&#xff09; 在64位编译模式下&#xff0c;指针的占用内存大小是8字节在32位编译模式下&#xff0c;指针占用内存大小是4字…

jmc线程转储_使线程转储智能化

jmc线程转储很久以前&#xff0c;我了解了一个称为Log MDC的东西&#xff0c;我对此非常感兴趣。 我突然意识到日志文件中发生的一切&#xff0c;并指出了特定的日志条目&#xff0c;并找到了对错&#xff0c;特别是在调试生产中的错误时。 2013年&#xff0c;我受委托从事一个…

【C语言】指针进阶第五站:函数指针!

点击蓝字关注我们函数指针函数也有自己的地址&#xff0c;函数名/&函数名 就是函数的地址1.1基本形式在 数组指针的学习中我们了解到int arr[5]; int (*pa)[5] &arr;//pa是数组指针指针变量pa的类型是int(*)[5]那么函数指针的形式是怎样的呢&#xff1f;void test(cha…

jsp 体检信息查询 绕过用户名验证_一篇彻底搞懂jsp

jsp 实栗 jsp jdbc 实现登录实现思路一个表单页&#xff0c;输入用户登录和密码&#xff0c;然后信息提交到jsp页面进行验证&#xff0c;如果可以服务器跳转到登录成功页&#xff0c;失败&#xff0c;跳转到错误页跳转的时候窗口的URL地址会发生变化代码如下编写登录代码登录&…

Python3求解找到小镇的法官问题

Python3求解找到小镇的法官问题原题 https://leetcode-cn.com/problems/find-the-town-judge/题目&#xff1a; 在一个小镇里&#xff0c;按从 1 到 N 标记了 N 个人。传言称&#xff0c;这些人中有一个是小镇上的秘密法官。 如果小镇的法官真的存在&#xff0c;那么&#xff…

couchbase_具有Rx-Java的Couchbase Java SDK

couchbase关于Couchbase Java SDK的一件整洁的事情是&#xff0c;它建立在出色的Rx-Java库的基础上&#xff0c;这为与Couchbase服务器实例进行交互提供了一种React性的方式&#xff0c;一旦掌握了它&#xff0c;它就非常直观。 考虑一个我打算存储在Couchbase中的非常简单的j…

C/C++与汇编混合编程有什么好处?

点击蓝字关注我们1 导语 当需要C/C与汇编混合编程时&#xff0c;可以有以下两种处理策略&#xff1a;若汇编代码较短&#xff0c;则可在C/C源文件中直接内嵌汇编语言实现混合编程。若汇编代码较长&#xff0c;可以单独写成汇编文件&#xff0c;最后以汇编文件的形式加入项目中&…

centos 7.6安装java_Hadoop的安装

为了方便后面使用Hadoop的shell命令&#xff0c;我先介绍Hadoop的安装。Hadoop有多种安装模式&#xff0c;这里介绍伪分布式的安装。我测试过Ubutun、Centos和WSL&#xff0c;都可以正常安装Hadoop的所有版本。所有一般不会出现版本对应的问题。Hadoop是基于Java语言进行编写的…

Python3 解题:字符串压缩

Python3 解题&#xff1a;字符串压缩原题 https://leetcode-cn.com/problems/compress-string-lcci/题目&#xff1a; 字符串压缩。利用字符重复出现的次数&#xff0c;编写一种方法&#xff0c;实现基本的字符串压缩功能。比如&#xff0c;字符串aabcccccaaa会变为a2b1c5a3。若…

C++软件分析师异常分析工作经验汇总

点击蓝字关注我们最近几年工作当中很大一部分内容是排查软件运行过程中遇到的各种异常&#xff0c;积累了一定的经验&#xff0c;在此给大家分享一下。本文将详细讲述Windows系统中软件异常的分类以及常用的排查方法&#xff0c;给大家提供一个借鉴与参考。1、软件异常的分类常…

java fix_Java中的低延迟FIX引擎

java fix总览 Chronicle FIX是我们的Low Latency FIX引擎和Java数据库。 是什么使它与众不同&#xff1f; 是为Java中的超低GC *设计的。 支持字符串和日期时间的方式可以最大程度地减少垃圾和开销。 可自定义为仅包含您期望的字段。 使用通常在二进制解析器和生成器中使用…

linux 查看防火墙状态_每天五分钟学习Linux系列之 - 系统安全配置

20年IT从业&#xff0c;二哥的团队使用最多的系统就是Linux&#xff0c;开发&#xff0c;运维的小伙伴们都离不开Linux系统&#xff0c;特别是大数据和人工智能领域更是如此&#xff0c;但由于日常工作忙&#xff0c;小伙伴们没有太多成块的时间系统的学习Linux, 并且现版CentO…

Python3求解旋转矩阵问题

Python3求解旋转矩阵问题原题 https://leetcode-cn.com/problems/spiral-matrix/ 给定一个包含 m x n 个元素的矩阵&#xff08;m 行, n 列&#xff09;&#xff0c;请按照顺时针螺旋顺序&#xff0c;返回矩阵中的所有元素。 示例 1: 输入: [[ 1, 2, 3 ],[ 4, 5, 6 ],[ 7, 8…

只针对异常的情况才使用异常_如何以及何时使用异常

只针对异常的情况才使用异常本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题&#xff0c;包括对象创建&#xff0c;并发&#xff0c;序列化&#xff0c;反射等。 它将指导您完成Java掌握的旅程&#xff01; 在这里查看…

C++红黑树模拟实现map和set

点击蓝字关注我们一、红黑树及其节点的设计对于底层都是红黑树的map和set来说&#xff0c;他们之间存在的最大的区别就是&#xff1a;对于set是K模型的容器&#xff0c;而map是KV模型的容器。为了更好的灵活兼容实现map和set&#xff0c;就需要在红黑树以及树节点上进行特别的设…

c语言连接mysql_聊聊数据库MySQL、SqlServer、Oracle的区别,哪个更适合你?

一、MySQL优点&#xff1a;体积小、速度快、总体拥有成本低&#xff0c;开源&#xff1b;支持多种操作系统&#xff1b;是开源数据库&#xff0c;提供的接口支持多种语言连接操作 &#xff1b;MySQL的核心程序采用完全的多线程编程。线程是轻量级的进程&#xff0c;它可以灵活地…

Python3解题:二叉树路径总和问题

Python3解题&#xff1a;二叉树路径总和问题原题 https://leetcode-cn.com/problems/path-sum-ii/ 给定一个二叉树和一个目标和&#xff0c;找到所有从根节点到叶子节点路径总和等于给定目标和的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 给定如下二叉树&#xff…