红黑树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 ...
随机推荐
- python3入门教程(一)之 hello world
概述 python 这门语言这几年非常的火,很多技术都用的到,像爬虫,大数据,人工智能等,包括很多的小孩都首选python作为入门学习语言,那python 究竟是怎样一门语言呢? Python 是一个 ...
- c# 抽象类与接口【学习笔记】
最近一直在学着面向接口编程,总是会写出好多的接口然后继承,现在开始发现了一些好处,就是在一个方法里面使用另一个方法的时候, 用接口代替这个被使用的方法,可以减少代码的耦合,后期的扩展也方便,代码易于维 ...
- 世界上最好的Sed教程
这是一份世界上最好的sed教程,sed是unix系统下流编辑里的超人.最初我写这份说明是为了我的 第二本电子书,然而随后我决定把这份说明变成一本免费电子书预览的同时再次做为文章发布到这里. Sed说明 ...
- java中的线程问题是(四)——线程同步问题
多线程的并发,给我们编程带来很多好处,完成更多更有效率的程序.但是也给我们带来线程安全问题. 解决问题的关键就是要保证容易出问题的代码的原子性,所谓原子性就是指:当a线程在执行某段代码的时候,别的线程 ...
- pycharm的中文汉化
下载pycharm软件 然后通过下面的网站进行激活: http://idea.lanyus.com/ 激活好后下载汉化包:链接:http://pan.baidu.com/s/1i5zaGgX 密码:g ...
- Spring 源码学习(1)—— 容器的基本实现
最近在读Spring的源码,参考的是郝佳的<Spring源码深度解析>,这里把一些学习心得分享一下,总结的地方可能还有一些不完善,希望大家指教 IoC(控制反转)是Spring的特性之一, ...
- 2/19 学习笔记(for in 、 del语句)
for x in ...循环就是把每个元素代入变量x,然后执行缩进块的语句 del语句作用在变量上,而不是数据对象上 列表可以修改,而字符串和元组不能
- 0913_Python初识及变量
1.Python3不需加utf-8,Python必须加utf-82.单行注释用#,多行注释用""" """3.变量:只能由字母.数字.下划线 ...
- python day 25--正则表达式
一.字符组 1.[0-9]表示匹配0-9中的数字 2.[a-z]表示匹配a-z之间的字母 3.[A-Z]表示匹配大写的字母 4.[0-9a-zA-Z]匹配所有字母数字 二.元字符 1.\d 匹配任意数 ...
- python day20面向对象-属性,类方法,静态方法
一.属性的初识 # class Person: # # def __init__(self,name,hight,weight): # self.name = name # self.__hight ...