树结构的python实现(三:红黑树)

以下为红黑树的python实现:

from enum import Enum
from binary_search_tree import AVLTree, Node  # binary_search_tree的代码见上一篇文章:https://blog.csdn.net/moyao_miao/article/details/136827024

Color = Enum('Color', ('red', 'black'))  # 枚举节点的颜色(红或黑)
Direction = Enum('Direction', ('left', 'right'))  # 枚举节点的方向(左或右)


class RedBlackNode(Node):
    """红黑树节点类"""
    def __init__(self, value):
        super().__init__(value)
        self.parent_node = None  # 增加属性记录父节点
        self.color = Color.red  # 初始化节点的颜色为红色

    def add(self, left: bool, value):
        """
        重写add,在添加新节点后绑定父节点,并返回添加的子节点。
        :param left:是否加在左子节点上
        :param value:节点值
        :return:添加的子节点
        """
        if left:
            self.left_node = self.instantiate_myself(value)
            self.left_node.parent_node = self
            return self.left_node
        else:
            self.right_node = self.instantiate_myself(value)
            self.right_node.parent_node = self
            return self.right_node


class RedBlackTree(AVLTree):
    """
    红黑树类
    **改进建议:**
    1. **支持更广泛的输入**:考虑让__init__方法支持空列表输入,并在后续添加元素时建立树的结构,这样可以提供更灵活的类使用方式。
    2. **性能优化**:如果`data_list`较大,当前的初始化方法可能会导致性能问题,尤其是如果后者是通过连续插入实现的。考虑实现更高效的批量构建树的策略,比如先排序`data_list`然后通过分治法创建平衡的红黑树等。
    3. **代码复用**: 如果出现了大量重复的逻辑操作或模式,可以考虑将其抽取到工具类或基类中,以提高代码的复用性和可维护性。
    """
    def __init__(self, data_list):
        self.root = RedBlackNode(data_list[0])
        self.root.color = Color.black  # 创建根节点,并将其颜色设置为黑色
        self._list_to_binarytree(data_list)

    def rotate_left(self, root):
        """重写左旋转,设置颜色并修改父节点指向"""
        axis = root.right_node
        root.color = Color.red
        axis.color = Color.black
        root.right_node = axis.left_node
        if axis.left_node: axis.left_node.parent_node = root
        axis.left_node = root
        axis.parent_node = root.parent_node
        root.parent_node = axis
        return axis

    def rotate_right(self, root):
        """重写右旋转,设置颜色并修改父节点指向"""
        axis = root.left_node
        root.color = Color.red
        axis.color = Color.black
        root.left_node = axis.right_node
        if axis.right_node: axis.right_node.parent_node = root
        axis.right_node = root
        axis.parent_node = root.parent_node
        root.parent_node = axis
        return axis

    def get_direction(self, node, parent_node):
        """获取子节点在父节点中的方向"""
        if parent_node is None: return
        return Direction.left if parent_node.left_node == node else Direction.right

    def rebalance(self, node):
        """
        递归恢复平衡
        :param node: 添加的节点,或需要调整平衡的节点
        :return: 最终返回的是根节点
        """
        parent_node = node.parent_node
        if parent_node:
            grandpa_node = parent_node.parent_node
            if grandpa_node is None: return parent_node# 如果爷爷节点不存在,说明父节点是根节点,不需要重平衡,直接返回父节点
            if parent_node.color == Color.red:
                uncle_node = grandpa_node.right_node if grandpa_node.left_node == parent_node else grandpa_node.left_node  # 获取叔叔节点
                if uncle_node and uncle_node.color == Color.red:
                    # 父节点和叔叔节点都是红色,则把爷爷节点设为红色(若是根节点则不用变色),父节点和叔叔节点设为黑色
                    if grandpa_node is not self.root: grandpa_node.color = Color.red
                    parent_node.color = uncle_node.color = Color.black
                else:
                    # 确定插入节点相对于父节点的方向和父节点相对于爷爷节点的方向
                    node_direction = self.get_direction(node, parent_node)
                    parent_direction = self.get_direction(parent_node, grandpa_node)
                    great_grandpa_node = grandpa_node.parent_node
                    grandpa_direction = self.get_direction(grandpa_node, great_grandpa_node)
                    if parent_direction == Direction.left:
                        # 左左情况右旋,左右情况左右旋
                        grandpa_node = self.rotate_right(grandpa_node) if node_direction == Direction.left else self.rotate_left_right(grandpa_node)
                    else:
                        # 右右情况左旋,右左情况右左旋
                        grandpa_node = self.rotate_left(grandpa_node) if node_direction == Direction.right else self.rotate_right_left(grandpa_node)
                    if grandpa_direction:
                        # 将调整后的爷爷节点链接到曾祖节点上
                        if grandpa_direction == Direction.left: great_grandpa_node.left_node = grandpa_node
                        else: great_grandpa_node.right_node = grandpa_node
                grandpa_node = self.rebalance(grandpa_node)  # 递归向上调整平衡
            return grandpa_node
        else:return node

    def _add(self, node, value):
        """重写_add,在添加节点后恢复红黑树平衡"""
        added_node = None
        while not added_node:
            if value < node.value:
                if node.left_node: node = node.left_node
                else: added_node = node.add(True, value)
            else:
                if node.right_node: node = node.right_node
                else: added_node = node.add(False, value)
        node = self.rebalance(added_node)
        return node

    def plot(self):
        """重写plot,在黑色节点上加下划线后缀_作区分"""
        def binarytree_to_list(node, line=0):
            nonlocal tree_list
            if line > len(tree_list) - 1: tree_list.append([])
            if node is None:
                tree_list[line].append('N')
                return
            else:tree_list[line].append(str(node.value) + ('_' if node.color == Color.black else ''))
            binarytree_to_list(node.left_node, line + 1)
            binarytree_to_list(node.right_node, line + 1)
            line -= 1

        tree_list = []
        binarytree_to_list(self.root)
        l = len(tree_list) - 1
        for i, line_list in enumerate(tree_list[:-1]):
            print((' ' * (l - i)).join([' ' * (l - i)] + line_list))

    def add_node(self, data):
        """重写add_node,每添加一个节点画一次图"""
        self.root = self._add(self.root, data)
        print(f'添加{data}之后的红黑树:')
        self.plot()


if __name__ == "__main__":
    def print_format(obj):
        print("中序遍历:");obj.inorder_traversal()
        print('红黑树图示:');obj.plot()

    data_list = [3, 5, 8, 4, 6, 7, 9, 2, 1]
    print_format(RedBlackTree(data_list))

输出:

添加5之后的红黑树:
    3_
  N 5
添加8之后的红黑树:
    5_
  3 8
添加4之后的红黑树:
      5_
    3_  8_
  N 4 N N
添加6之后的红黑树:
      5_
    3_  8_
  N 4 6 N
添加7之后的红黑树:
      5_
    3_  7_
  N 4 6 8
添加9之后的红黑树:
        5_
      3_   7
    N  4  6_  8_
  N N N N N 9
添加2之后的红黑树:
        5_
      3_   7
    2  4  6_  8_
  N N N N N N N 9
添加1之后的红黑树:
        5_
      3   7
    2_  4_  6_  8_
  1 N N N N N N 9
中序遍历:
1	2	3	4	5	6	7	8	9	

红黑树图示:
        5_
      3   7
    2_  4_  6_  8_
  1 N N N N N N 9

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 红黑树是一种自平衡二叉查找树,用于在O(log n)时间内完成查找、插入和删除等操作。Python是一种高级编程语言,可以使用Python语言编写红黑树。 下面是一个使用Python实现红黑树的示例代码: ```python class Node: def __init__(self, value): self.value = value self.left = None self.right = None self.parent = None self.color = "red" class RedBlackTree: def __init__(self): self.root = None def insert(self, value): node = Node(value) if self.root is None: self.root = node node.color = "black" else: self._insert(node) def _insert(self, node): parent = None current = self.root while current is not None: parent = current if node.value < current.value: current = current.left else: current = current.right node.parent = parent if parent is None: self.root = node elif node.value < parent.value: parent.left = node else: parent.right = node node.color = "red" self._insert_fixup(node) def _insert_fixup(self, node): while node.parent is not None and node.parent.color == "red": if node.parent == node.parent.parent.left: uncle = node.parent.parent.right if uncle is not None and uncle.color == "red": node.parent.color = "black" uncle.color = "black" node.parent.parent.color = "red" node = node.parent.parent else: if node == node.parent.right: node = node.parent self._left_rotate(node) node.parent.color = "black" node.parent.parent.color = "red" self._right_rotate(node.parent.parent) else: uncle = node.parent.parent.left if uncle is not None and uncle.color == "red": node.parent.color = "black" uncle.color = "black" node.parent.parent.color = "red" node = node.parent.parent else: if node == node.parent.left: node = node.parent self._right_rotate(node) node.parent.color = "black" node.parent.parent.color = "red" self._left_rotate(node.parent.parent) self.root.color = "black" def _left_rotate(self, node): right = node.right node.right = right.left if right.left is not None: right.left.parent = node right.parent = node.parent if node.parent is None: self.root = right elif node == node.parent.left: node.parent.left = right else: node.parent.right = right right.left = node node.parent = right def _right_rotate(self, node): left = node.left node.left = left.right if left.right is not None: left.right.parent = node left.parent = node.parent if node.parent is None: self.root = left elif node == node.parent.left: node.parent.left = left else: node.parent.right = left left.right = node node.parent = left ``` 这是一个简单的红黑树实现,其中包含了节点类`Node`和红黑 ### 回答2: 红黑树是一种自平衡的二叉搜索树,它保持了树的平衡性和强大的搜索效率。下面是用Python实现红黑树的一种简单方法: 首先,创建一个名为RedBlackTree的类,该类代表红黑树数据结构。在类的初始化方法中,我们可以定义空树和设置根节点。根节点是一个Node类的实例,每个节点有值、左孩子、右孩子、父节点和颜色属性。 接下来,我们可以定义插入方法insert(value),它接受一个值作为参数,并将该值插入到红黑树中。插入操作分为两个步骤:首先,按照二叉搜索树的规则找到插入位置;其次,根据红黑树的特性进行调整,保持树的平衡。 在插入操作中,我们需要考虑四种情况进行调整:当前节点的父节点是红色,当前节点的叔节点是红色,当前节点是父节点的右孩子,和当前节点是父节点的左孩子。对于每种情况,我们可以定义一些辅助方法,如左旋、右旋、变色等,来帮助我们实现平衡。 例如,当当前节点的父节点是红色,我们需要进行变色和旋转操作来保持平衡。具体步骤是:将当前节点和父节点都变成黑色,将当前节点的祖父节点变为红色,然后以祖父节点为支点进行左旋或右旋。 最后,我们可以实现搜索和删除方法,使红黑树具备完整的功能。 总之,通过使用Python的类和方法,我们可以轻松地实现红黑树的插入、搜索和删除。这种数据结构可以应用于各种场景,如有序集合、字典等,以提高搜索和插入的效率。 ### 回答3: 红黑树是一种自平衡的二叉搜索树,它具有以下特征:节点为红色或黑色,根节点为黑色,叶子节点(NIL节点)为黑色,红色节点的子节点必须为黑色,从根节点到任意叶子节点的路径上,黑色节点的数量相同。 为了实现一个红黑树,我们可以使用Python编程语言。下面是一个简单的红黑树实现的示例代码: ```python # 定义红黑树节点类 class Node: def __init__(self, key, parent=None, color='black', left=None, right=None): self.key = key self.parent = parent self.color = color self.left = left self.right = right class RedBlackTree: def __init__(self): self.root = None def insert(self, key): node = Node(key) # 插入节点 if self.root is None: node.color = 'black' self.root = node else: current = self.root parent = None while current is not None: parent = current if node.key < current.key: current = current.left else: current = current.right node.parent = parent if node.key < parent.key: parent.left = node else: parent.right = node # 调整红黑树 self.fix_insert(node) def fix_insert(self, node): while node.parent.color == 'red': if node.parent == node.parent.parent.left: uncle = node.parent.parent.right if uncle.color == 'red': node.parent.color = 'black' uncle.color = 'black' node.parent.parent.color = 'red' node = node.parent.parent else: if node == node.parent.right: node = node.parent self.left_rotate(node) node.parent.color = 'black' node.parent.parent.color = 'red' self.right_rotate(node.parent.parent) else: uncle = node.parent.parent.left if uncle.color == 'red': node.parent.color = 'black' uncle.color = 'black' node.parent.parent.color = 'red' node = node.parent.parent else: if node == node.parent.left: node = node.parent self.right_rotate(node) node.parent.color = 'black' node.parent.parent.color = 'red' self.left_rotate(node.parent.parent) self.root.color = 'black' def left_rotate(self, node): right = node.right node.right = right.left if right.left is not None: right.left.parent = node right.parent = node.parent if node.parent is None: self.root = right elif node == node.parent.left: node.parent.left = right else: node.parent.right = right right.left = node node.parent = right def right_rotate(self, node): left = node.left node.left = left.right if left.right is not None: left.right.parent = node left.parent = node.parent if node.parent is None: self.root = left elif node == node.parent.right: node.parent.right = left else: node.parent.left = left left.right = node node.parent = left def inorder_traversal(self, node): if node is not None: self.inorder_traversal(node.left) print(node.key) self.inorder_traversal(node.right) # 使用示例 tree = RedBlackTree() tree.insert(10) tree.insert(5) tree.insert(20) tree.insert(15) tree.insert(25) tree.inorder_traversal(tree.root) ``` 上述代码通过定义红黑树节点类,以及插入、修复插入的函数实现红黑树的基本功能。代码包括左旋、右旋、插入修复等操作。 这只是一个简单的红黑树实现示例,实际上,红黑树实现还有其他很多细节和优化。对于大规模或者更复杂的问题,建议使用现有的Python库来实现红黑树

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值