返回

用Python平衡二叉搜索树

闲谈

平衡二叉搜索树

平衡二叉搜索树是一种特殊的二叉搜索树,其左右子树的高度差不会超过1。这种特性使得平衡二叉搜索树的查找、插入和删除操作的时间复杂度都为O(log n),其中n是树中的节点数。

实现平衡二叉搜索树的方法

在Python中,实现平衡二叉搜索树有两种常见的方法:AVL树和红黑树。

  • AVL树:AVL树是一种高度平衡的二叉搜索树,其左右子树的高度差不会超过1。AVL树的插入和删除操作都可以在O(log n)的时间内完成。
  • 红黑树:红黑树也是一种高度平衡的二叉搜索树,其左右子树的高度差不会超过2。红黑树的插入和删除操作都可以在O(log n)的时间内完成。

代码示例

以下是使用AVL树和红黑树实现平衡二叉搜索树的代码示例:

# AVL树
class AVLNode:
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None
        self.height = 1

class AVLTree:
    def __init__(self):
        self.root = None

    def insert(self, key):
        new_node = AVLNode(key)
        self._insert(new_node)

    def _insert(self, new_node):
        if self.root is None:
            self.root = new_node
        else:
            self._insert_helper(new_node, self.root)

    def _insert_helper(self, new_node, current_node):
        if new_node.key < current_node.key:
            if current_node.left is None:
                current_node.left = new_node
            else:
                self._insert_helper(new_node, current_node.left)
        else:
            if current_node.right is None:
                current_node.right = new_node
            else:
                self._insert_helper(new_node, current_node.right)

        self._update_height(current_node)
        self._balance(current_node)

    def _update_height(self, current_node):
        current_node.height = 1 + max(self._get_height(current_node.left), self._get_height(current_node.right))

    def _get_height(self, node):
        if node is None:
            return 0
        else:
            return node.height

    def _balance(self, current_node):
        balance_factor = self._get_balance_factor(current_node)

        # 左子树太高
        if balance_factor > 1:
            # 左子树的左子树太高
            if self._get_balance_factor(current_node.left) < 0:
                self._left_rotate(current_node.left)

            # 右旋转
            self._right_rotate(current_node)

        # 右子树太高
        elif balance_factor < -1:
            # 右子树的右子树太高
            if self._get_balance_factor(current_node.right) > 0:
                self._right_rotate(current_node.right)

            # 左旋转
            self._left_rotate(current_node)

    def _get_balance_factor(self, node):
        if node is None:
            return 0
        else:
            return self._get_height(node.left) - self._get_height(node.right)

    def _left_rotate(self, node):
        right_child = node.right
        node.right = right_child.left
        right_child.left = node

        self._update_height(node)
        self._update_height(right_child)

    def _right_rotate(self, node):
        left_child = node.left
        node.left = left_child.right
        left_child.right = node

        self._update_height(node)
        self._update_height(left_child)

# 红黑树
class RBNode:
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None
        self.color = "red"

class RBTree:
    def __init__(self):
        self.root = None

    def insert(self, key):
        new_node = RBNode(key)
        self._insert(new_node)

    def _insert(self, new_node):
        if self.root is None:
            self.root = new_node
        else:
            self._insert_helper(new_node, self.root)

    def _insert_helper(self, new_node, current_node):
        if new_node.key < current_node.key:
            if current_node.left is None:
                current_node.left = new_node
            else:
                self._insert_helper(new_node, current_node.left)
        else:
            if current_node.right is None:
                current_node.right = new_node
            else:
                self._insert_helper(new_node, current_node.right)

        self._fix_insert(new_node)

    def _fix_insert(self, new_node):
        self._set_color(new_node, "red")

        while new_node != self.root and self._get_color(new_node.parent) == "red":
            if new_node.parent == new_node.parent.parent.left:
                uncle_node = new_node.parent.parent.right

                # 叔叔节点是红色
                if self._get_color(uncle_node) == "red":
                    self._set_color(new_node.parent, "black")
                    self._set_color(uncle_node, "black")
                    self._set_color(new_node.parent.parent, "red")
                    new_node = new_node.parent.parent

                # 叔叔节点是黑色
                else:
                    if new_node == new_node.parent.right:
                        new_node = new_node.parent
                        self._left_rotate(new_node)

                    self._set_color(new_node.parent, "black")
                    self._set_color(new_node.parent.parent, "red")
                    self._right_rotate(new_node.parent.parent)
            else:
                uncle_node = new_node.parent.parent.left

                # 叔叔节点是红色
                if self._get_color(uncle_node) == "red":
                    self._set_color(new_node.parent, "black")
                    self._set_color(uncle_node, "black")
                    self._set_color(new_node.parent.parent, "red")
                    new_node = new_node.parent.parent

                # 叔叔节点是黑色
                else:
                    if new_node == new_node.parent.left:
                        new_node = new_node.parent
                        self._right_rotate(new_node)

                    self._set_color(new_node.parent, "black")
                    self._set_color(new_node.parent.parent, "red")
                    self._left_rotate(new_node.parent.parent)

        self._set_color(self.root, "black")

    def _set_color(self, node, color):
        if node is not None:
            node.color = color

    def _get_color(self, node):
        if node is None:
            return "black"
        else:
            return node.color

    def _left_rotate(self, node):
        right_child = node.right
        node.right = right_child.left
        right_child.left = node

        self._set_color(node, "red")
        self._set_color(right_child, "black")

    def _right_rotate(self, node):
        left