栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

红黑树python实现

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

红黑树python实现

原理讲解参考:https://www.cnblogs.com/skywang12345/p/3245399.html

'''
1) 每个节点是黑色或者红色。
2) 根节点是黑色。
3) 每个叶子节点(nil)是黑色。
4) 红色节点的子节点必须是黑色。
5) 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
'''


import random


class Color:
    Red = 1
    Black = 2

class NullNode:
    def __init__(self):
        self.color = Color.Black
        self.parent = None 
        self.left = None
        self.right = None

class RbTreeNode:
    def __init__(self, key, color):
        self.key = key 
        self.color = color
        self.parent = NullNode() 
        self.left = NullNode() 
        self.right = NullNode() 

    def format(self):
        if self.color == Color.Red:
            return "33[31m%s33[0m" % self.key 
        else:
            return "33[34m%s33[0m" % self.key 

def left_rotate(t, x):
    p = x.parent
    r = x.right 
    
    # 右节点设为父节点
    r.parent = p 
    if x == p.left:
        p.left = r 
    else:
        p.right = r 

    # 右左节点设置x的右节点
    r.left.parent = x 
    x.right = r.left

    # x设为左节点
    r.left = x 
    x.parent = r 

    if not r.parent or isinstance(r.parent, NullNode):
        t = r 
    return t 
    
def right_rotate(t, x):
    p = x.parent 
    l = x.left 

    l.parent = p 
    if x == p.left:
        p.left = l 
    else:
        p.right = l 

    l.right.parent = x 
    x.left = l.right 

    l.right = x 
    x.parent = l 

    if not l.parent or isinstance(l.parent, NullNode):
        t = l 
    return t 

def insert(t, key):
    z = RbTreeNode(key, Color.Red)

    y = NullNode()
    x = t 

    while x and not isinstance(x, NullNode):
        y = x 
        if z.key < x.key:
            x = x.left 
        else:
            x = x.right 

    z.parent = y 
    if not y or isinstance(y, NullNode):
        t = z 
        print(t)
    elif z.key < y.key:
        y.left = z 
    else:
        y.right = z 

    print_tree(t)
    return insert_fixup(t, z)
    
# 有bug,待修复
def insert_fixup(t, z):
    while z.parent.color == Color.Red:
        if z.parent == z.parent.parent.left:
            y = z.parent.parent.right 
            if y.color == Color.Red:
                z.parent.color = Color.Black 
                y.color = Color.Black
                z.parent.parent.color = Color.Red 
                z = z.parent.parent 
            else:
                if z == z.parent.right:
                    z = z.parent 
                    t = left_rotate(t, z)
                
                z.parent.color = Color.Black
                z.parent.parent.color = Color.Red
                t = right_rotate(t, z.parent.parent)

        else:
            y = z.parent.parent.left 
            if y.color == Color.Red:
                z.parent.color = Color.Black 
                y.color = Color.Black
                z.parent.parent.color = Color.Red 
                z = z.parent.parent 
            else:
                if z == z.parent.left:
                    z = z.parent 
                    t = right_rotate(t, z)
                
                z.parent.color = Color.Black
                z.parent.parent.color = Color.Red
                t = left_rotate(t, z.parent.parent)

    t.color = Color.Black 
    return t

def delete(t, key):
    z = NullNode()
    y = NullNode()
    x = t 
    while x and not isinstance(x, NullNode):
        if key < x.key:
            x = x.left 
        elif key > x.key:
            x = x.right 
        else:
            z = x 
            break 

    if isinstance(z, NullNode):
        return t 

    if isinstance(z.left, NullNode) or isinstance(z.right, NullNode):
        y = z 
    else:
        y = tree_successor(z)

    if not isinstance(y.left, NullNode):
        x = y.left 
    else:
        x = y.right 

    x.parent = y.parent 
    if isinstance(y.parent, NullNode):
        t = x 
    elif y == y.parent.left:
        y.parent.left = x 
    else:
        y.parent.right = x 
    
    if y != z:
        z.key = y.key 

    if y.color == Color.Black:
        t = delete_fixup(t, x)
    return t 

def delete_fixup(t, x):
    while x != t and x.color == Color.Black:
        if x == x.parent.left:
            w = x.parent.right 
            if w.color == Color.Red:
                w.color = Color.Black 
                t = left_rotate(t, x.parent)
                w = x.parent.right 
            if w.left.color == Color.Black and w.right.color == Color.Black:
                w.color = Color.Red 
                x = x.parent 
            elif w.right.color == Color.Black:
                w.left.color = Color.Black 
                w.color = Color.Red 
                t = right_rotate(t, w)
                w = x.parent.right 
            
            w.color = x.parent.color 
            x.parent.color = Color.Black 
            w.right.color = Color.Black 
            t = left_rotate(t, x.parent)
            x = t 
        else:
            w = x.parent.left 
            if w.color == Color.Red:
                w.color = Color.Black 
                t = right_rotate(t, x.parent)
                w = x.parent.left 
            if w.right.color == Color.Black and w.left.color == Color.Black:
                w.color = Color.Red 
                x = x.parent 
            elif w.left.color == Color.Black:
                w.right.color = Color.Black 
                w.color = Color.Red 
                t = left_rotate(t, w)
                w = x.parent.left 
            
            w.color = x.parent.color 
            x.parent.color = Color.Black 
            w.left.color = Color.Black 
            t = right_rotate(t, x.parent)
            x = t 

    x.color = Color.Black
    return t

def tree_successor(x):
    y = x.right 
    z = NullNode()
    while y and not isinstance(y, NullNode):
        z = y
        y = y.left 

    return z 


def set_parent(p, l, r):
    p.left = l 
    p.right = r 
    l.parent = p
    r.parent = p 

def format_tree(t):
    if not t or isinstance(t, NullNode):
        return 0, []

    left_indent, left_tree = format_tree(t.left)
    right_indent, right_tree = format_tree(t.right)

    tree = []
    tree.append("."*left_indent + t.format() + "."*right_indent)
    n = 0 
    while n < len(left_tree) or n < len(right_tree):
        line = ""
        if n < len(left_tree):
            line += left_tree[n]
        else:
            line += " "*left_indent

        line += " "*len(str(t.key))
        if n < len(right_tree):
            line += right_tree[n]
        else:
            line += " "*right_indent
        tree.append(line)

        n += 1

    indent = left_indent + len(str(t.key)) + right_indent
    return indent, tree

def print_tree(t):
    # print("------------")
    _, tree = format_tree(t)
    for line in tree:
        print(line)

if __name__ == "__main__":
    # a = RbTreeNode("a", Color.Red)
    # b = RbTreeNode("b", Color.Red)
    # c = RbTreeNode("c", Color.Red)
    # d = RbTreeNode("d", Color.Red)

    # set_parent(a, b, NullNode())
    # set_parent(b, c, d)
    # print_tree(a)

    # # left_rotate(a, b)
    # right_rotate(a, b)
    # print_tree(a)

    # a = RbTreeNode("a", Color.Black)
    # b = RbTreeNode("b", Color.Red)
    # set_parent(a, NullNode(), b)
    # t = a
    # print_tree(t)
    # t = insert(t, "c")
    # print_tree(t)

    t = NullNode()
    for i in range(30):
        n = random.randint(0, 10)
        print("------ ", n)
        t = insert(t, n)
        print_tree(t)

    print("*******************")
    for i in range(10):
        n = random.randint(0, 10)
        print("------ ", n)
        t = delete(t, n)
        print_tree(t)
    # for key in [chr(x) for x in range(ord('a'), ord('z') + 1)]:
    #     t = insert(t, key)
    #     print_tree(t)


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1004711.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号