红黑树插入概况

来源:互联网 发布:如何雇佣网络水军价格 编辑:程序博客网 时间:2024/06/04 18:37

红黑树插入概况


在理解红黑树原理的基础上,总结下代码的书写思路和步骤

  • 数据结构
  • 插入
  • 调整
  • 旋转

什么是红黑树?

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.

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)
原创粉丝点击