红黑树Python实现
# 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实现的更多相关文章
- 红黑树-Python实现
		
#coding:utf8 #author:HaxtraZ #description:红黑树,python实现 RED = 'red' BLACK = 'black' class RBT: def __ ...
 - 红黑树:个人理解与Python实现
		
红黑树:个人理解与Python实现 [基本事实1] 红黑树是一种平衡的二叉查找树,无论插入还是删除操作都可以在O(lg n)内实现,而一般的二叉查找树则在极端情况下会退化为线性结构.红黑树之所以是平衡 ...
 - 算法导论 第十三章 红黑树(python)-1插入
		
红黑树是上一章二叉搜索树的改进,实现一种平衡 ,保证不会出现二叉树变链表的情况,基本动态集合操作的时间复杂度为O(lgn) 实际用途:c++stl中的set,map是用他实现的 红黑树的性质: 1.每 ...
 - 彻底理解红黑树及JavaJDK1.8TreeMap源码分析
		
1. 定义 红黑树也是二叉查找树,我们知道,二叉查找树这一数据结构并不难,而红黑树之所以难是难在它是自平衡的二叉查找树,在进行插入和删除等可能会破坏树的平衡的操作时,需要重新自处理达到平衡状态.红黑树 ...
 - Java实现红黑树(平衡二叉树)
		
前言 在实现红黑树之前,我们先来了解一下符号表. 符号表的描述借鉴了Algorithms第四版,详情在:https://algs4.cs.princeton.edu/home/ 符号表有时候被称为字典 ...
 - 红黑树——算法导论(15)
		
1. 什么是红黑树 (1) 简介 上一篇我们介绍了基本动态集合操作时间复杂度均为O(h)的二叉搜索树.但遗憾的是,只有当二叉搜索树高度较低时,这些集合操作才会较快:即当树的高度较高(甚至一种极 ...
 - jdk源码分析红黑树——插入篇
		
红黑树是自平衡的排序树,自平衡的优点是减少遍历的节点,所以效率会高.如果是非平衡的二叉树,当顺序或逆序插入的时候,查找动作很可能会遍历n个节点 红黑树的规则很容易理解,但是维护这个规则难. 一.规则 ...
 - 谈c++ pb_ds库(二) 红黑树大法好
		
厉害了,没想到翻翻pb_ds库看到这么多好东西,封装好的.现成的splay.红黑树.avl... 即使不能在考场上使用也可以用来对拍哦 声明/头文件 #include <ext/pb_ds/tr ...
 - 定时器管理:nginx的红黑树和libevent的堆
		
libevent 发生超时后, while循环一次从堆顶del timer——直到最新调整的最小堆顶不是超时事件为止,(实际是del event),但是会稍后把这个timeout的 event放到ac ...
 
随机推荐
- day20_python_1124
			
01 昨日内容回顾 类的名称空间 对象的空间 class A: def __init__(): pass obj = A() 对象查询属性:对象本身 ----> 类 -----> 父类 类 ...
 - css隐藏滚动条依旧可以滚动
			
在做企业页面的时候,大部分页面都应该是活的,不应该写死,因为要从后台拿数据进行填充.而后台的数据是不确定的,有时候会让我们的容器撑得很大.这时候我们需要隐藏掉滚动条达到美观或者其他布局效果,隐藏掉单个 ...
 - css样式 + 特殊符号
			
color控制字体颜色 十六进制值 #cc0066: font-size控制字体大小 单位 px / % / em / rem:像素 / 相对于父级元素 / 取决自己使用字体大小 / 取决于根元素ht ...
 - pycharm中添加PATH变量
			
最近在pycharm中run程序,终端terminal没有问题,在pycharm找不到$PATH中的变量值,如下图所示 同样的命令,在终端敲就没毛病,终端echo $PATH的时候,显示的是有cuda ...
 - Python全栈之路----常用模块----os模块
			
os模块提供了很多允许你的程序和操作系统直接交互的功能 得到当前工作目录,即当前Python脚本工作的目录路径:os.getcwd() #test.py import os print(os.getc ...
 - python学习之路04——列表和字典
			
列表和字典 python中的可变数据类型有:列表和字典 不可变类型:数字,字符串,元组 今天先讲列表和字典 一.列表 1.概念: 变量:使用变量存储数据,但是,变量存储数据每次只能存储一个数据 问题: ...
 - Parsing with Compositional Vector Grammars--paper
			
这篇和2012年的区别: 1)Max-Margin Training Objective J中RNN变为了CVG 2012-两个词向量合并并打分,这个-两个(词向量,POS)合并并打分 2012年: ...
 - java中的映射表HashMap、TreeMap
			
集(set)是集合(collection),集合不是集. HashMap是散列映射.TreeMap对键进行排序了. map的三个视图:键集.值集合.键/值集. Set<K> keySet( ...
 - 学习笔记TF046:TensoFlow开发环境,Mac、Ubuntu/Linux、Windows,CPU版本、GPU版本
			
下载TensorFlow https://github.com/tensorflow/tensorflow/tree/v1.1.0 .Tags选择版本,下载解压. pip安装.pip,Python包管 ...
 - _Bool and bool
			
_Bool is the defined before C99. bool has been defined in C99. bool is an alias for _Bool if you inc ...