# coding=utf-8
# 红黑树Python实现
# 颜色常量
RED =
0
BLACK = 1
def left_rotate(tree, node):
if not node.right:
return False
node_right =
node.right
node_right.p =
node.p
if not node.p:
tree.root =
node_right
elif node ==
node.p.left:
node.p.left =
node_right
else:
node.p.right =
node_right
if node_right.left:
node_right.left.p =
node
node.right =
node_right.left
node.p =
node_right
node_right.left =
node
def right_rotate(tree, node):
if not node.left:
return False
node_left =
node.left
node_left.p =
node.p
if not node.p:
tree.root =
node_left
elif node ==
node.p.left:
node.p.left =
node_left
elif node ==
node.p.right:
node.p.right =
node_left
if node_left.right:
node_left.right.p =
node
node.left =
node_left.right
node.p =
node_left
node_left.right =
node
def transplant(tree, node_u, node_v):
"""
用 v 替换 u
:param tree: 树的根节点
:param node_u: 将被替换的节点
:param node_v: 替换后的节点
:return: None
"""
if not node_u.p:
tree.root =
node_v
elif node_u ==
node_u.p.left:
node_u.p.left =
node_v
elif node_u ==
node_u.p.right:
node_u.p.right =
node_v
# 加一下为空的判断
if node_v:
node_v.p =
node_u.p
def tree_maximum(node):
"""
找到以 node 节点为根节点的树的最大值节点 并返回
:param node: 以该节点为根节点的树
:return: 最大值节点
"""
temp_node =
node
while temp_node.right:
temp_node =
temp_node.right
return temp_node
def tree_minimum(node):
"""
找到以 node 节点为根节点的树的最小值节点 并返回
:param node: 以该节点为根节点的树
:return: 最小值节点
"""
temp_node =
node
while temp_node.left:
temp_node =
temp_node.left
return temp_node
def preorder_tree_walk(node):
if node:
print (node.value, node.color)
preorder_tree_walk(node.left)
preorder_tree_walk(node.right)
class RedBlackTreeNode(object):
def __init__(self, value):
self.value =
value
self.left =
None
self.right =
None
self.p =
None
self.color =
RED
class RedBlackTree(object):
def __init__(self):
self.root =
None
def insert(self, node):
# 找到最接近的节点
temp_root =
self.root
temp_node =
None
while temp_root:
temp_node =
temp_root
if node.value ==
temp_node.value:
return False
elif node.value >
temp_node.value:
temp_root =
temp_root.right
else:
temp_root =
temp_root.left
# 在相应位置插入节点
if not temp_node:
self.root =
node
node.color =
BLACK
elif node.value <
temp_node.value:
temp_node.left =
node
node.p =
temp_node
else:
temp_node.right =
node
node.p =
temp_node
# 调整树
self.insert_fixup(node)
def insert_fixup(self, node):
if node.value ==
self.root.value:
return
# 为什么是这个终止条件?
# 因为如果不是这个终止条件那就不需要调整
while node.p
and node.p.color ==
RED:
# 只要进入循环则必有祖父节点 否则父节点为根节点 根节点颜色为黑色 不会进入循环
if node.p ==
node.p.p.left:
node_uncle =
node.p.p.right
# 1. 没有叔叔节点 若此节点为父节点的右子 则先左旋再右旋 否则直接右旋
# 2. 有叔叔节点 叔叔节点颜色为黑色
# 3. 有叔叔节点 叔叔节点颜色为红色 父节点颜色置黑 叔叔节点颜色置黑 祖父节点颜色置红 continue
# 注: 1 2 情况可以合为一起讨论 父节点为祖父节点右子情况相同 只需要改指针指向即可
if node_uncle
and node_uncle.color ==
RED:
node.p.color =
BLACK
node_uncle.color =
BLACK
node.p.p.color =
RED
node =
node.p.p
continue
elif node ==
node.p.right:
left_rotate(self, node.p)
node =
node.left
node.p.color =
BLACK
node.p.p.color =
RED
right_rotate(self, node.p.p)
return
elif node.p ==
node.p.p.right:
node_uncle =
node.p.p.left
if node_uncle
and node_uncle.color ==
RED:
node.p.color =
BLACK
node_uncle.color =
BLACK
node.p.p.color =
RED
node =
node.p.p
continue
elif node ==
node.p.left:
right_rotate(self, node)
node =
node.right
node.p.color =
BLACK
node.p.p.color =
RED
left_rotate(self, node.p.p)
return
# 最后记得把根节点的颜色改为黑色 保证红黑树特性
self.root.color =
BLACK
def delete(self, node):
# 找到以该节点为根节点的右子树的最小节点
node_color =
node.color
if not node.left:
temp_node =
node.right
transplant(self, node, node.right)
elif not node.right:
temp_node =
node.left
transplant(self, node, node.left)
else:
# 最麻烦的一种情况 既有左子 又有右子 找到右子中最小的做替换 类似于二分查找树的删除
node_min =
tree_minimum(node.right)
node_color =
node_min.color
temp_node =
node_min.right
if node_min.p !=
node:
transplant(self, node_min, node_min.right)
node_min.right =
node.right
node_min.right.p =
node_min
transplant(self, node, node_min)
node_min.left =
node.left
node_min.left.p =
node_min
node_min.color =
node.color
# 当删除的节点的颜色为黑色时 需要调整红黑树
if node_color ==
BLACK:
self.delete_fixup(temp_node)
def delete_fixup(self, node):
# 实现过程还需要理解 比如为什么要删除 为什么是那几种情况
while node != self.root
and node.color ==
BLACK:
if node ==
node.p.left:
node_brother =
node.p.right
if node_brother.color ==
RED:
node_brother.color =
BLACK
node.p.color =
RED
left_rotate(self, node.p)
node_brother =
node.p.right
if (
not node_brother.left
or node_brother.left.color == BLACK)
and \
(not node_brother.right
or node_brother.right.color ==
BLACK):
node_brother.color =
RED
node =
node.p
else:
if not node_brother.right
or node_brother.right.color ==
BLACK:
node_brother.color =
RED
node_brother.left.color =
BLACK
right_rotate(self, node_brother)
node_brother =
node.p.right
node_brother.color =
node.p.color
node.p.color =
BLACK
node_brother.right.color =
BLACK
left_rotate(self, node.p)
node =
self.root
break
else:
node_brother =
node.p.left
if node_brother.color ==
RED:
node_brother.color =
BLACK
node.p.color =
RED
left_rotate(self, node.p)
node_brother =
node.p.right
if (
not node_brother.left
or node_brother.left.color == BLACK)
and \
(not node_brother.right
or node_brother.right.color ==
BLACK):
node_brother.color =
RED
node =
node.p
else:
if not node_brother.left
or node_brother.left.color ==
BLACK:
node_brother.color =
RED
node_brother.right.color =
BLACK
left_rotate(self, node_brother)
node_brother =
node.p.left
node_brother.color =
node.p.color
node.p.color =
BLACK
node_brother.left.color =
BLACK
right_rotate(self, node.p)
node =
self.root
break
node.color =
BLACK
def main():
number_list = (7, 4, 1, 8, 5, 2, 9, 6, 3
)
tree =
RedBlackTree()
for number
in number_list:
node =
RedBlackTreeNode(number)
tree.insert(node)
del node
preorder_tree_walk(tree.root)
tree.delete(tree.root)
preorder_tree_walk(tree.root)
if __name__ ==
'__main__':
main()
教材
: 算法导论(第三版)
转载于:https://www.cnblogs.com/wuditju/p/5992129.html