欢迎访问宙启技术站
智能推送

Python函数实现高级数据结构——红黑树

发布时间:2023-06-20 17:16:59

红黑树是一种平衡二叉搜索树(BST),在其节点上存储额外的信息来保持树的平衡。这些额外信息包括颜色和黑高度,其中红黑色节点是一种标准。

红黑树的定义和规则

红黑树必须满足以下规则:

1. 每个节点要么是红色,要么是黑色。

2. 根节点必须是黑色。

3. 每个叶子节点(NIL节点,空节点)都是黑色的。

4. 如果一个节点是红色的,则其子节点都必须是黑色的(反之不一定成立)。

5. 从根节点到每个叶子节点的所有路径都必须包含相同数量的黑色节点,称为黑高度。

红黑树的插入

插入一个节点到红黑树中的步骤如下:

1. 将节点插入到BST中,并涂成红色。

2. 检查节点的父节点,如果父节点为黑色,则插入完毕,树仍然满足红黑树的规则。

3. 如果父节点为红色,则进行以下操作,直到根节点为止:

   a. 如果叔节点(父节点的兄弟节点)为红色,则将父节点和叔节点涂成黑色,祖父节点涂成红色,并将当前节点变为祖父节点,继续操作。

   b. 如果叔节点为黑色,并且当前节点是其父节点的右子节点(父节点为左子节点),则将父节点左旋。

   c. 如果叔节点为黑色,并且当前节点是其父节点的左子节点(父节点为右子节点),则将父节点右旋。

4. 最后,将根节点涂成黑色。

红黑树的删除

删除节点的步骤如下:

1. 找到要删除的节点,并将其替换为其子节点(如果有的话)。

2. 如果被删除的节点或其替换节点是红色的,则不需要任何操作,树仍然满足红黑树的规则。

3. 如果被删除的节点或其替换节点是黑色的,则进行以下操作:

   a. 如果替换节点为红色,则将其涂成黑色。

   b. 如果替换节点为黑色,并且其兄弟节点为红色,则将兄弟节点和其父节点颜色交换,并进行旋转操作,使得删除节点的新兄弟节点为黑色。

   c. 如果替换节点为黑色,并且其兄弟节点为黑色,则根据兄弟节点的子节点情况进行以下三种情况的操作:

      (1) 兄弟节点的子节点都为黑色,则将兄弟节点涂成红色,并将当前节点指向其父节点。

      (2) 兄弟节点的左子节点为红色,右子节点为黑色,则将兄弟节点左旋,并交换其颜色为红色。

      (3) 兄弟节点的右子节点为红色,则将兄弟节点涂成其父节点的颜色,将其父节点涂成黑色,将兄弟节点的右子节点涂成黑色,并将其父节点右旋。

4. 最后,将根节点涂成黑色。

红黑树的实现

红黑树可以使用Python语言中的类和对象进行实现。以下是一个简单的实现:

`python

class Node():

    def __init__(self, val=None, color='R', left=None, right=None, parent=None):

        self.val = val

        self.color = color

        self.left = left

        self.right = right

        self.parent = parent

class RedBlackTree():

    def __init__(self, root=None):

        self.root = root

    

    def insert(self, val):

        node = Node(val=val)

        if not self.root:

            self.root = node

        else:

            parent = None

            cur = self.root

            while cur:

                parent = cur

                if node.val < cur.val:

                    cur = cur.left

                else:

                    cur = cur.right

            node.parent = parent

            if node.val < parent.val:

                parent.left = node

            else:

                parent.right = node

            self._insert_fixup(node)

    

    def _insert_fixup(self, node):

        while node.parent and node.parent.color == 'R':

            if node.parent == node.parent.parent.left:

                uncle = node.parent.parent.right

                if uncle and uncle.color == 'R':

                    node.parent.color = 'B'

                    uncle.color = 'B'

                    node.parent.parent.color = 'R'

                    node = node.parent.parent

                else:

                    if node == node.parent.right:

                        node = node.parent

                        self._left_rotate(node)

                    node.parent.color = 'B'

                    node.parent.parent.color = 'R'

                    self._right_rotate(node.parent.parent)

            else:

                uncle = node.parent.parent.left

                if uncle and uncle.color == 'R':

                    node.parent.color = 'B'

                    uncle.color = 'B'

                    node.parent.parent.color = 'R'

                    node = node.parent.parent

                else:

                    if node == node.parent.left:

                        node = node.parent

                        self._right_rotate(node)

                    node.parent.color = 'B'

                    node.parent.parent.color = 'R'

                    self._left_rotate(node.parent.parent)

        self.root.color = 'B'

    

    def _left_rotate(self, node):

        y = node.right

        node.right = y.left

        if y.left:

            y.left.parent = node

        y.parent = node.parent

        if not node.parent:

            self.root = y

        elif node == node.parent.left:

            node.parent.left = y

        else:

            node.parent.right = y

        y.left = node

        node.parent = y

    

    def _right_rotate(self, node):

        y = node.left

        node.left = y.right

        if y.right:

            y.right.parent = node

        y.parent = node.parent

        if not node.parent:

            self.root = y

        elif node == node.parent.right:

            node.parent.right = y

        else:

            node.parent.left = y

        y.right = node

        node.parent = y

    

    def delete(self, val):

        node = self.search(val)

        if not node:

            return

        if not node.left or not node.right:

            child = node.left or node.right

            if not child:

                node = None

            else:

                child.parent = node.parent

                if not node.parent:

                    self.root = child

                elif node == node.parent.left:

                    node.parent.left = child

                else:

                    node.parent.right = child

                if node.color == 'B':

                    self._delete_fixup(child)

        else:

            successor = self._find_min(node.right)

            node.val = successor.val

            self.delete(successor.val)

    

    def _delete_fixup(self, node):

        while node != self.root and node.color == 'B':

            if node == node.parent.left:

                sibling = node.parent.right

                if sibling.color == 'R':

                    sibling.color = 'B'

                    node.parent.color = 'R'

                    self._left_rotate(node.parent)

                    sibling = node.parent.right

                if (not sibling.left or sibling.left.color == 'B') and (not sibling.right or sibling.right.color == 'B'):

                    sibling.color = 'R'

                    node = node.parent

                else:

                    if not sibling.right or sibling.right.color == 'B':

                        sibling.left.color = 'B'

                        sibling.color = 'R'

                        self._right_rotate(sibling)

                        sibling = node.parent.right

                    sibling.color = node.parent.color

                    node.parent.color = 'B'

                    sibling.right.color = 'B'

                    self._left_rotate(node.parent)

                    node = self.root

            else:

                sibling = node.parent.left

                if sibling.color == 'R':

                    sibling.color = 'B'

                    node.parent.color = 'R'

                    self._right_rotate(node.parent)

                    sibling = node.parent.left

                if (not sibling.left or sibling.left.color == 'B') and (not sibling.right or sibling.right.color == 'B'):

                    sibling.color = 'R'

                    node = node.parent

                else