# 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()
教材: 算法导论(第三版)

红黑树Python实现的更多相关文章

  1. 红黑树-Python实现

    #coding:utf8 #author:HaxtraZ #description:红黑树,python实现 RED = 'red' BLACK = 'black' class RBT: def __ ...

  2. 红黑树:个人理解与Python实现

    红黑树:个人理解与Python实现 [基本事实1] 红黑树是一种平衡的二叉查找树,无论插入还是删除操作都可以在O(lg n)内实现,而一般的二叉查找树则在极端情况下会退化为线性结构.红黑树之所以是平衡 ...

  3. 算法导论 第十三章 红黑树(python)-1插入

    红黑树是上一章二叉搜索树的改进,实现一种平衡 ,保证不会出现二叉树变链表的情况,基本动态集合操作的时间复杂度为O(lgn) 实际用途:c++stl中的set,map是用他实现的 红黑树的性质: 1.每 ...

  4. 彻底理解红黑树及JavaJDK1.8TreeMap源码分析

    1. 定义 红黑树也是二叉查找树,我们知道,二叉查找树这一数据结构并不难,而红黑树之所以难是难在它是自平衡的二叉查找树,在进行插入和删除等可能会破坏树的平衡的操作时,需要重新自处理达到平衡状态.红黑树 ...

  5. Java实现红黑树(平衡二叉树)

    前言 在实现红黑树之前,我们先来了解一下符号表. 符号表的描述借鉴了Algorithms第四版,详情在:https://algs4.cs.princeton.edu/home/ 符号表有时候被称为字典 ...

  6. 红黑树——算法导论(15)

    1. 什么是红黑树 (1) 简介     上一篇我们介绍了基本动态集合操作时间复杂度均为O(h)的二叉搜索树.但遗憾的是,只有当二叉搜索树高度较低时,这些集合操作才会较快:即当树的高度较高(甚至一种极 ...

  7. jdk源码分析红黑树——插入篇

    红黑树是自平衡的排序树,自平衡的优点是减少遍历的节点,所以效率会高.如果是非平衡的二叉树,当顺序或逆序插入的时候,查找动作很可能会遍历n个节点 红黑树的规则很容易理解,但是维护这个规则难. 一.规则 ...

  8. 谈c++ pb_ds库(二) 红黑树大法好

    厉害了,没想到翻翻pb_ds库看到这么多好东西,封装好的.现成的splay.红黑树.avl... 即使不能在考场上使用也可以用来对拍哦 声明/头文件 #include <ext/pb_ds/tr ...

  9. 定时器管理:nginx的红黑树和libevent的堆

    libevent 发生超时后, while循环一次从堆顶del timer——直到最新调整的最小堆顶不是超时事件为止,(实际是del event),但是会稍后把这个timeout的 event放到ac ...

随机推荐

  1. Sonya and Robots(CodeForces 1004C)

    Since Sonya is interested in robotics too, she decided to construct robots that will read and recogn ...

  2. 为DBNavigator的按钮加中文

    转自:http://hi.baidu.com/debiansir/item/0699f5b6bb4d99f063388e71 /*Delphi中数据库控件DBNavigator使用起来不错,但是按钮上 ...

  3. Saiku免登录嵌入其他系统使用(十一)

    Saiku免登录嵌入其他系统使用 Saiku可通过iframe嵌入其他系统使用,但是正常情况下都需要先登录系统,然后还需要登录saiku,最后才能访问saiku中的数据 下面来讲解一下如何使Saiku ...

  4. .net core webapi带权限的文件下载方法

    众所周知,在webapi中,如果有个接口需要权限,一般会将带权限的字段塞进header中.但是,在带权限的文档下载接口中,无论是用post,还是get方式,我们无法设置header头信息.苦恼呀?别急 ...

  5. 查询系统正在运行的SQL语句

    查询系统正在运行的SQL语句: select a.program, b.spid, c.sql_text from v$session a, v$process b, v$sqlarea c wher ...

  6. SAZ文件的打开与保存

    保存 在Fiddler上,使用菜单“文件”>“保存” 可以将当前的HTTP请求信息保存成SAZ文件.   读取 在Fiddler上,使用菜单“文件”>“加载档案”可以读取SAZ文件,加载其 ...

  7. # 20175120 2018.3.3 《Java程序设计》第1周学习总结

    ## 教材学习内容总结 1.安装ubuntu,在实验楼学习liunx系统各种功能的实现.2.在ubuntu平台上进行java程序的编写3.学会使用JDB调试java程序,并将代码上传到码云上4.学习j ...

  8. python -django 之第三方支付

    神魔是第三方支付: 第三方支付是指具有一定实力和信誉保障的第三方独立机构.通过与各大银行签订合同,建立连接用户和银行支付结算系统的平台,从而实现电子支付模式.从另一个角度来看,第三方支付就是非金融机构 ...

  9. python定时发信息给女友

    第一步,也是最难的一部 首先得要有个女朋友 利用python的第三方库wxpy来登录微信,实现消息发送功能 from wxpy import * def login(): bot = Bot(cach ...

  10. python: 文件的读写

    #文件的读取.py a=open('test.txt').readline() #只读取文件第一行,保存为字符串格式 b=open('test.txt').read() #读取全部内容,保存为字符串格 ...