红黑树插入概况
来源:互联网 发布:如何雇佣网络水军价格 编辑:程序博客网 时间:2024/06/04 18:37
红黑树插入概况
在理解红黑树原理的基础上,总结下代码的书写思路和步骤
- 数据结构
- 插入
- 调整
- 旋转
什么是红黑树?
A red-black tree is a binary tree that satisfies the following red-black properties:
- Every node is either red or black.
- The root is black.
- Every leaf (NIL) is black.
- If a node is red, then both its children are black.
- For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.
1. 数据结构
Node 是三个指针+一个关键字+一个颜色,初始化时除了key,都为None;RBtree 保存根节点(.root)和叶子节点(.nil)
class TreeNode:#红黑树的节点信息,5个,除了key,其他都可以初始化为None def __init__(self, key): self.key = key self.p = None self.left = None self.right = None self.color = Noneclass RBtree:#两个节点信息 def __init__(self): self.nil = TreeNode(0)#把nil初始化为一个节点 self.root = self.nil self.nil.p = self.nil self.nil.left = self.nil self.nil.right = self.nil self.nil.color = 'black'
2. 插入
插入分三步:寻找、连接、初始化
def InserdNode(T, Node): y = T.nil # y永远是x父亲 x = T.root #x从根开始作为参照点 while x != T.nil: #寻找:找Node的位置 循环不变量:每次循环开始时,y为x的父亲 y = x #保证下一次循环y为x父亲 if Node.key < x.key: x = x.left else: x = x.right Node.p = y #连接:对y与Node的关系分三种情况。这个模式常见 if y == T.nil: T.root = Node elif Node.key <= y.key: y.left = Node else: y.right = Node Node.left = T.nil #初始化 Node.right = T.nil Node.color = 'red' InsertFixup(T, Node)
3. 调整
1). z.p不红时,不进入while循环,强制下T.root.color为红即可.
2). 当z和z.p都红时进入while循环调整,共有两大类,每类又分三种情况,后三种只需要把前三种的代码中左指针右指针反过来。关键上把前三种情况理清。
根据z父亲左孩子还是右孩子分大类;
根据z叔叔是红黑分小类,红为情况一,黑为情况二、三;
根据z自己是左孩子还是右孩子来分情况二、三.
下面两幅图告诉我们如何处理上面三种情况:
图一:
图二:
def InsertFixup(T, z): while z.p.color == 'red': if z.p == z.p.p.left: #第一大类,z的parent是爷爷的长孙 y = z.p.p.right #z的uncle是红,三变色,不旋转 if y.color == 'red':#情况1 z.p.color = 'black' y.color = 'black' z.p.p.color = 'red' z = z.p.p#z上升两层 else: if z == z.p.right:#情况2,z的uncle黑,z不是长孙 z = z.p LeftRotate(T, z) z.p.color = 'black'#情况3 z.p.p.color = 'red' RightRotate(T, z.p.p) else:#第二大类 y = z.p.p.left if y.color == 'red':#情况4,z的uncle是红, z.p.color = 'black' y.color = 'black' z.p.p.color = red z = z.p.p#z上升两层 else: if z == z.p.left:#情况5,z的uncle黑,z是长孙 z = z.p RightRotate(T, z) z.p.color = 'black'#情况6 z.p.p.color = 'red' LeftRotate(T, z.p.p) T.root.color = 'black'
4. 旋转
旋转分为左旋和右旋,右旋只需把左旋代码中的左右指针设为相反。
旋转时先(x,y)的上面,再(x,y)的下面,最后自己(x和y).
对照如下图:
def LeftRotate(T, x): y = x.right y.p = x.p #先顶层:把与y与x的父亲连接好 if x == T.root: T.root = y elif x == x.p.left: x.p.left = y else: x.p.right = y x.right = y.left#再底层:把x和y丢失的孩子连好 y.left.p = x x.p = y#最后中间:把x和y连好 y.left = xdef RightRotate(T, x): y = x.left y.p = x.p #先顶层:把x的父亲和y先连接好 if x == T.root: T.root = y elif x == x.p.right: x.p.right = y else: x.p.left = y x.left = y.right#再底层:把x和y丢失的孩子连好 y.right.p = x x.p = y#最后中间:把x和y连好 y.right = x
附上整个工程的代码
# utf-8'''A red-black tree is a binary tree that satisfies the following red-black properties: 1. Every node is either red or black. 2. The root is black. 3. Every leaf (NIL) is black. 4. If a node is red, then both its children are black. 5. For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.'''class TreeNode:# 红黑树的节点信息,5个,除了key,其他都可以初始化为None def __init__(self, key): self.key = key self.p = None self.left = None self.right = None self.color = Noneclass RBtree:#两个节点信息 def __init__(self): self.nil = TreeNode(0)#把nil初始化为一个节点 self.root = self.nil self.nil.p = self.nil self.nil.left = self.nil self.nil.right = self.nil self.nil.color = 'black'def InserdNode(T, Node): y = T.nil # y永远是x父亲 x = T.root #x从根开始作为参照点 while x != T.nil: #find Node's parent, 循环不变量:每次循环开始时,y为x的父亲 y = x # 保证下一次循环y为x父亲 if Node.key < x.key: x = x.left else: x = x.right Node.p = y #insert Node if y == T.nil: #分三种情况插入Node T.root = Node elif Node.key <= y.key: y.left = Node #print(Node.key) else: y.right = Node #print(Node.key) Node.left = T.nil #initial node Node.right = T.nil Node.color = 'red' InsertFixup(T, Node) #print('Key: %s color: %s' %(Node.key, Node.color))def InOderTravel(T, x): if x == T.nil: return else: InOderTravel(T, x.left) print('Key: %s color: %s' %(x.key,x.color)) InOderTravel(T, x.right)def InsertFixup(T, z):#Node z is red #if z.p is root, z.p is black # while z.p.color == 'red': if z.p == z.p.p.left: #第一大类,z的parent是爷爷的长孙 y = z.p.p.right #z的uncle是红,三变色,不旋转 if y.color == 'red':#情况1 z.p.color = 'black' y.color = 'black' z.p.p.color = 'red' z = z.p.p#z上升两层 else: if z == z.p.right:#情况2,z的uncle黑,z不是长孙 z = z.p LeftRotate(T, z) z.p.color = 'black'#情况3 z.p.p.color = 'red' RightRotate(T, z.p.p) else:#第二大类 y = z.p.p.left if y.color == 'red':#情况4,z的uncle是红, z.p.color = 'black' y.color = 'black' z.p.p.color = red z = z.p.p#z上升两层 else: if z == z.p.left:#情况5,z的uncle黑,z是长孙 z = z.p RightRotate(T, z) z.p.color = 'black'#情况6 z.p.p.color = 'red' LeftRotate(T, z.p.p) T.root.color = 'black'def LeftRotate(T, x): y = x.right y.p = x.p #先顶层:把与y与x的父亲连接好 if x == T.root: T.root = y elif x == x.p.left: x.p.left = y else: x.p.right = y x.right = y.left#再底层:把x和y丢失的孩子连好 y.left.p = x x.p = y#最后中间:把x和y连好 y.left = xdef RightRotate(T, x): y = x.left y.p = x.p #先顶层:把x的父亲和y先连接好 if x == T.root: T.root = y elif x == x.p.right: x.p.right = y else: x.p.left = y x.left = y.right#再底层:把x和y丢失的孩子连好 y.right.p = x x.p = y#最后中间:把x和y连好 y.right = xT = RBtree()keylist = [41, 38, 31, 12, 19, 8]for key in keylist: InserdNode(T, TreeNode(key))#print(T.root.left.key, T.root.right.key)InOderTravel(T, T.root)
阅读全文
0 0
- 红黑树插入概况
- 组织概况
- 东京大学概况
- 活动概况
- JFreeChart概况
- 南宁概况
- AJAX 概况
- 监利概况
- YsuhyORM 概况
- AJAX 概况
- Cassandra 概况
- 集训概况
- 菜单【概况】
- Struts2 概况
- UML概况
- GPS概况
- lucene概况
- JQuery概况
- 第九章自定义标签第五节简单标签
- Python string.format() 的用法
- URL之get、post 乱码处理
- F-35 战斗机的代码量达到 800 万行,C语言竟然占到424万行,看来航电系统还得靠C(纯C)。
- Java中Object类的方法(toString方法和equals方法)
- 红黑树插入概况
- C# 调用c++错误A call to PInvoke function has unbalanced the stack
- CSS3伪类实现背景动态切换
- HDU 2159-FATE-背包
- HDOJ2091 空心三角形
- 【Win10】修改标题栏颜色
- ssm框架整合
- Codeforces Round #446 (Div. 2) D. Gluttony
- 7面向对象方法学