Python3 atteindre arbre rouge-noir [Partie I]

Python3 atteindre arbre rouge-noir [Partie I]

En raison des contraintes de temps, mais cette fois pour écrire un arbre rouge-noir pour ajouter des nœuds, des nœuds de suppression placés sur le côté de parler https://blog.csdn.net/qq_18138105/article/details/105324025 .

Introduction, la raison, la nature et la définition de l' arbre rouge-noir, vous pouvez voir l'article ici, ce ne sera pas les répéter: arbre rouge-noir, graphique super mouvement détaillé, facile à comprendre

A propos de l' arbre rouge-noir, en fait, relativement facile à comprendre ceci est la « gauche » et « droitier ».

Comme il est en rotation , il doit y avoir un point d'appui et de spin, il est l'axe de pivotement, rotation autour du point d' appui dans le sens horaire ou antihoraire rotation.
Puis, « gauche » et « droitier » à la fin qui est dans le sens horaire, anti - horaire qui est - il?
Ici, le point d'appui rotatif doit être un noeud parent, qui est supérieure à la position du point de pivot de rotation, de sorte que L est dans le sens antihoraire en rotation, la rotation dans le sens horaire est droitier!

Pour la rotation, partager des formules:

右旋: 支点占旋点原位,支点的右给旋点作为左,旋点作为支点的右,交换支点和旋点的颜色
左旋: 支点占旋点原位,支点的左给旋点作为右,旋点作为支点的左,交换支点和旋点的颜色

Pour emprunter le Grand Dieu de la figure 2. Comme on le voit ci - dessous, est comme un point d' appui à p, g processus de dextrose pour voir si elle répond aux formules ci - dessus: Après le dextrose, le point d'articulation p occupe g de spin in situ, le point d' appui P de la T3 point de rotation à droite comme le g gauche, comme le point de rotation g de droite p .
Insérer ici l'image Description
Regard L: Après le L, le point d' appui g p occupe une rotation sur place, le point d' appui P du point T3 rotation à gauche et à droite , comme le G et G en tant que point de rotation à gauche de p . De plus en ligne avec les formules ci - dessus.
Insérer ici l'image Description

Ce qui suit est le code pour python3 insertion noeud d'arbre rouge-noir processus.

# 红黑树节点
class RBN(object):
    def __init__(self, data):
        self.data = data  # 数据域
        self.color = 0  # 0红 1黑
        self.left = None
        self.right = None
        self.parent = None


# 红黑树
class RBT(object):
    def __init__(self):
        self.root = None

    # 中序遍历
    def midTraverse(self, x):
        if x == None:
            return
        self.midTraverse(x.left)
        colorStr = '黑' if x.color == 1 else '红'
        parentStr = '父=' + ('nil' if x.parent == None else str(x.parent.data))
        print(x.data, colorStr, parentStr)
        self.midTraverse(x.right)

    # 添加一个节点
    def add(self, x):
        # 如果没有根节点 作为根节点
        if self.root == None:
            self.root = x
            x.color = 1  # 根节点为黑色
            # print('添加成功', x.data)
            return
        # 寻找合适的插入位置
        p = self.root
        while p != None:
            if x.data < p.data:
                if p.left == None:
                    p.left = x
                    x.parent = p
                    # print('添加成功', x.data)
                    self.addFix(x)
                    break
                p = p.left
            elif x.data > p.data:
                if p.right == None:
                    p.right = x
                    x.parent = p
                    # print('添加成功', x.data)
                    self.addFix(x)
                    break
                p = p.right
            else:
                return

    # 调整红黑树
    def addFix(self, x):
        while True:
            if x == self.root:  # 如果处理到根节点了 则着色为黑
                x.color = 1
                return
            p = x.parent  # 爸爸
            if p.color == 1 or x.color == 1:  # 自己和爸爸只要有一个是黑的 就构不成双红 则返回
                return
            # 接下来分析红爸爸情况
            g = p.parent  # 爷爷 红爸爸肯定有爸爸,因为红色绝不是根节点
            u = g.left if p == g.right else g.right  # 叔叔 叔叔可能为空节点
            if u != None and u.color == 0:  # 红叔叔 则着色 然后从爷爷开始向上继续调整
                u.color = p.color = 1  # 叔叔和爸爸都变黑色
                g.color = 0  # 爷爷变红色
                x = g  # x指向爷爷,然后继续循环
                continue
            # 接下来分析黑叔叔得情况 有四种情况 左左,左右,右左,右右
            if p == g.left and x == p.left:  # 左左
                # 以爸爸为支点右旋爷爷
                self.rotateRight(p)
            elif p == g.left and x == p.right:  # 左右
                # 以x为支点左旋爸爸
                self.rotateLeft(x)
                # 以x为支点右旋爷爷(上面的旋转把爷爷变成了新爸爸)
                self.rotateRight(x)
            elif p == g.right and x == p.right:  # 右右 其实就是 左左的镜像
                # 以爸爸为支点左旋爷爷
                self.rotateLeft(p)
            elif p == g.right and x == p.left:  # 右左 其实就是 左右的镜像
                # 以x为支点右旋爸爸
                self.rotateRight(x)
                # 以x为支点左旋爷爷(上面的旋转把爷爷变成了新爸爸)
                self.rotateLeft(x)

    #
    # 关于红黑树的旋转,一直是个难搞的点
    # 这里我提供一个口诀:
    #   右旋: 支点占旋点原位,支点的右给旋点作为左,旋点作为支点的右
    #   左旋: 支点占旋点原位,支点的左给旋点作为右,旋点作为支点的左
    #
    # 右旋 p支点
    def rotateRight(self, p):
        g = p.parent  # 支点的父节点就是旋点
        # 右旋g
        if g == self.root:  # 若g是根节点 则p升为根节点
            self.root = p
            p.parent = None
        else:  # 若g不是根节点 那么必然存在g.parent p占据g的位置
            gp = g.parent
            p.parent = gp
            if g == gp.left:
                gp.left = p
            else:
                gp.right = p
        g.left = p.right
        if p.right != None:
            p.right.parent = g
        p.right = g
        g.parent = p
        # g和p颜色交换
        p.color, g.color = g.color, p.color

    # 左旋 p 支点
    def rotateLeft(self, p):
        g = p.parent  # 支点的父节点就是旋点
        # 左旋g
        if g == self.root:  # 若g是根节点 则p升为根节点
            self.root = p
            p.parent = None
        else:  # 若g不是根节点 那么必然存在g.parent p占据g的位置
            gp = g.parent
            p.parent = gp
            if g == gp.left:
                gp.left = p
            else:
                gp.right = p
        g.right = p.left
        if p.left != None:
            p.left.parent = g
        p.left = g
        g.parent = p
        # g和p颜色交换
        p.color, g.color = g.color, p.color


if __name__ == '__main__':
    rbt = RBT()

    datas = [10, 20, 30, 15]
    # datas = [11, 2, 14, 1, 7, 15, 5, 8, 4]
    for x in datas:
        rbt.add(RBN(x))

    rbt.midTraverse(rbt.root)

La suppression du nœud d'arbre rouge-noir, voir la décomposition de la prochaine fois .

Publié 24 articles originaux · louanges gagnées 0 · Vues 410

Je suppose que tu aimes

Origine blog.csdn.net/qq_18138105/article/details/105190887
conseillé
Classement