Python之红黑树

简介: 笔记

红 黑 树

RBTree

2.png

完整代码如下:

NIL = Node(-1, 1, None, None)
NIL.left = NIL
NIL.right = NIL
class Node:
    def __init__(self, key = -1, color = 0, left = NIL, right = NIL):
        self.key = key
        self.color = color
        self.left = left
        self.right = right
    def __repr__(self):
        return "[" + str(self.key) + "-" + str(self.color) + ": (" + str(self.left.key) + "-" + str(self.left.color) + ", " + str(self.right.key) + "-" + str(self.right.key) + ")]"     
class RBTree:
    def __init__(self, root = NIL):
        self.root = root
    def insert(self, key):
        self.root = self.__insert(self.root, key)
        self.root.color = 1
        return self.root
    def __insert(self, root, key):
        if root == NIL:
            return Node(key)
        if root.key == key:
            return root
        if root.key < key:
            root.right = self.__insert(root.right, key)
        else:
            root.left = self.__insert(root.left, key)
        return self.insert_maintain(root)
    def insert_maintain(self, root):
        if not self.has_red_child(root):
            return root
        if root.left.color == 0 and root.right.color == 0:
            if not self.has_red_child(root.left) and not self.has_red_child(root.right):
                return root
            root.color = 0
            root.left.color = root.right.color = 1
            return root
        if root.left.color == 0 and not self.has_red_child(root.left):
            return root
        if root.right.color == 0 and not self.has_red_child(root.right):
            return root
        if root.left.color == 0:
            if root.left.right.color == 0:
                root.left = self.left_rotate(root.left)
            root = self.right_rotate(root)
        else:
            if root.right.left.color == 0:
                root.right = self.right_rotate(root.right)
            root = self.left_rotate(root)
        root.color = 0
        root.left.color = root.right.color = 1
        return root
    def erase(self, key):
        self.root = self.__erase(self.root, key)
        self.root.color = 1
        return self.root
    def __erase(self, root, key):
        if root == NIL:
            return NIL
        if root.key < key:
            root.right = self.__erase(root.right, key)
        elif root.key > key:
            root.left = self.__erase(root.left, key)
        else:
            if root.left == NIL or root.right == NIL:
                tmp = root.left if root.left != NIL else root.right
                tmp.color += root.color
                del root
                return tmp
            tmp = self.get_pre(root)
            root.key = tmp.key
            root.left = self.__erase(root.left, tmp.key)
        return self.erase_maintain(root)
    def erase_maintain(self, root):
        if root.left.color != 2 and root.right.color != 2:
            return root
        if self.has_red_child(root):
            root.color = 0
            if root.left.color == 0:
                root = self.right_rotate(root)
                root.right = self.erase_maintain(root.right)
            else:
                root = self.left_rotate(root)
                root.left = self.erase_maintain(root.left)
            root.color = 1
            return root
        if root.left.color == 2 and not self.has_red_child(root.right) or root.right.color == 2 and not self.has_red_child(root.left):
            root.left.color -= 1
            root.right.color -= 1
            root.color += 1
            return root
        if root.left.color == 2:
            root.left.color = 1
            if root.right.right.color != 0:
                root.right.color = 0
                root.right = self.right_rotate(root.right)
                root.right.color = 1
            root = self.left_rotate(root)
            root.color = root.left.color
        else:
            root.right.color = 1
            if root.left.left.color != 0:
                root.left.color = 0
                root.left = self.left_rotate(root.left)
                root.left.color = 1
            root = self.right_rotate(root)
            root.color = root.right.color
        root.left.color = root.right.color = 1
        return root
    def left_rotate(self, root):
        tmp = root.right
        root.right = tmp.left
        tmp.left = root
        return tmp
    def right_rotate(self , root):
        tmp = root.left
        root.left = tmp.right
        tmp.right = root
        return tmp
    def get_pre(self, root):
        tmp = root.left
        while tmp.right != NIL:
            tmp = tmp.right
        return tmp
    def has_red_child(self, root):
        return root.left.color == 0 or root.right.color == 0
    def inorder(self, root):
        if root.left != NIL:
            self.inorder(root.left)
        print(root)
        if root.right != NIL:
            self.inorder(root.right)
        return None

测试代码:

t = RBTree()
for i in range(1, 7):
    t.insert(i)
    if i % 3 == 0:
        t.erase(i - 1)
t.inorder(t.root)


🔴⚫️🌲


😊性质

每个节点非黑即红

根节点一定是黑色

叶子节点(NIL)是黑色

如果节点是红色,那么它的两个子节点都是黑色

从根节点到叶节点的所有路径,黑色节点数量相同

由性质4、5可推知:红黑树中,最长路径 == 2倍最短路径


💸Node

NIL节点,作为空节点(叶子节点)使用,默认单重黑。这样便于操作

正常新建节点,默认color为红,这样最大程度不影响性质5

红节点:没有子节点 or 两个黑色子节点

黑节点:如果只有一个子节点,那么必定是红色


🔫RBTree

封装红黑树的主要方法插入和删除


由于根节点到路径长度最坏相差一半,所以红黑树是一个基本平衡的二叉搜索树。

它没有AVL树那么绝对平衡,但是红黑树相比AVL旋转操作要少,而且删除操作也比AVL树效率更高。


👕insert

调整策略:


首先明确插入调整站在祖父节点看。(相当于做了一个延时操作)

其次插入调整是为了解决两个红色节点相邻的问题


🐱Case1 🐱

黑红红: 采取红色上浮,变为红黑黑

4.png

🐶Case2🐶

黑红黑:LL失衡,大右旋(如下图2),变为红黑黑

5.png6.png

🍗erase

调整策略:


红色节点


度0:直接删

度1:不存在

度2:转为前驱

黑色节点


度0:双黑顶替(延时)

度1:红色点互换

度2:转为前驱

首先明确删除调整是站在父节点 上

其次删除调整是为了调整双黑节点

🐯Case1🐯

兄弟黑+兄弟孩子黑:双黑上浮,黑红黑


7.png

🐻Case2🐻

兄弟黑+兄弟同侧孩子红:RR失衡,大左旋(如下图2),根变孩子颜色(右旋右孩子),孩子都变黑,双黑少一重8.png9.png

🐼Case3🐼

同case2: 不过先小旋(新根变黑,老根变红),在大旋

10.png11.png

  • 如果兄弟红,那么就旋成黑,就可以啦(O(∩_∩)O)

不要忘了,每次插入或删除操作后,根强制为黑

相关文章
|
9月前
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
533 1
|
存储 监控 算法
员工电脑监控场景下 Python 红黑树算法的深度解析
在当代企业管理范式中,员工电脑监控业已成为一种广泛采用的策略性手段,其核心目标在于维护企业信息安全、提升工作效能并确保合规性。借助对员工电脑操作的实时监测机制,企业能够敏锐洞察潜在风险,诸如数据泄露、恶意软件侵袭等威胁。而员工电脑监控系统的高效运作,高度依赖于底层的数据结构与算法架构。本文旨在深入探究红黑树(Red - Black Tree)这一数据结构在员工电脑监控领域的应用,并通过 Python 代码实例详尽阐释其实现机制。
241 7
|
存储 算法 Java
【每日算法】比较哈希表与红黑树两种实现 |Python 主题月
【每日算法】比较哈希表与红黑树两种实现 |Python 主题月
|
算法 Python
红黑树:个人理解与Python实现
红黑树:个人理解与Python实现   【基本事实1】 红黑树是一种平衡的二叉查找树,无论插入还是删除操作都可以在O(lg n)内实现,而一般的二叉查找树则在极端情况下会退化为线性结构。红黑树之所以是平衡的二叉查找树,是因为每个节点都有表示其颜色的域值:红或黑,在插入和删除操作的时候依据节点的颜色向平衡的方向调整。
1243 0
|
7月前
|
数据采集 机器学习/深度学习 人工智能
Python:现代编程的首选语言
Python:现代编程的首选语言
1058 102
|
7月前
|
数据采集 机器学习/深度学习 算法框架/工具
Python:现代编程的瑞士军刀
Python:现代编程的瑞士军刀
435 104
|
7月前
|
人工智能 自然语言处理 算法框架/工具
Python:现代编程的首选语言
Python:现代编程的首选语言
342 103
|
7月前
|
机器学习/深度学习 人工智能 数据挖掘
Python:现代编程的首选语言
Python:现代编程的首选语言
307 82
|
6月前
|
Python
Python编程:运算符详解
本文全面详解Python各类运算符,涵盖算术、比较、逻辑、赋值、位、身份、成员运算符及优先级规则,结合实例代码与运行结果,助你深入掌握Python运算符的使用方法与应用场景。
434 3
|
6月前
|
数据处理 Python
Python编程:类型转换与输入输出
本教程介绍Python中输入输出与类型转换的基础知识,涵盖input()和print()的使用,int()、float()等类型转换方法,并通过综合示例演示数据处理、错误处理及格式化输出,助你掌握核心编程技能。
644 3

推荐镜像

更多