Python3 lograr árbol rojo-negro [Parte I]

Python3 lograr árbol rojo-negro [Parte I]

Por falta de tiempo, sólo que esta vez para escribir un árbol rojo-negro para agregar nodos, los nodos de borrado colocados en el lado hablan https://blog.csdn.net/qq_18138105/article/details/105324025 .

Introducción, la razón, la naturaleza y definición de árbol rojo-negro, se puede ver el artículo en el presente documento, esto no va a repetir: árbol rojo-negro, gráfico del movimiento súper detallada, fácil de entender

Acerca de árbol rojo-negro, de hecho, relativamente fácil de resolver esto es la " izquierda " y " mano derecha ".

Puesto que se rota , entonces debe ser un punto de apoyo y el giro, que es el eje de pivote, la rotación alrededor del fulcro punto de las agujas del reloj o en sentido antihorario de rotación.
Entonces, "izquierda" y "mano derecha" en el extremo, que es hacia la derecha, hacia la izquierda, que es?
Aquí, el punto de apoyo giratorio debe ser un nodo padre, que es más alta que la posición del punto de fulcro de rotación, por lo que L es girada hacia la izquierda, giro a la derecha es la mano derecha!

Para la rotación, comparten un fórmulas:

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

Para tomar prestado el Gran Dios de la figura 2. Como se muestra a continuación, es como un punto de apoyo para p, g proceso de dextrosa para ver si cumple con las fórmulas anteriores: Después de dextrosa, punto p fulcro ocupa g giro in situ, el punto de apoyo P de la derecha T3 punto de rotación como el g izquierda, como el punto de rotación g de la p derecho .
Aquí Insertar imagen Descripción
Look L: Después de la L, el punto de apoyo el punto g p ocupa un giro in situ, el p punto de apoyo de la T3 punto de rotación izquierda y derecha como la g y g como punto de rotación izquierda de p . También en línea con las fórmulas anteriores.
Aquí Insertar imagen Descripción

El siguiente es el código para python3 inserción nodo del árbol rojo-negro proceso.

# 红黑树节点
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 eliminación del nodo de árbol rojo-negro, ver siguiente descomposición de tiempo .

Publicado 24 artículos originales · ganado elogios 0 · Vistas 410

Supongo que te gusta

Origin blog.csdn.net/qq_18138105/article/details/105190887
Recomendado
Clasificación