Python函数实现高级数据结构——红黑树
红黑树是一种平衡二叉搜索树(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
