(四)用go实现红黑树

本篇文章我们用go来实现红黑树,部分参考资料如下:

1.节点定义

type RBNode struct {
    color uint8 
    key Type
    left, right, parent *RBNode
}

type RBRoot struct {
    node *RBNode
}

2.树的遍历

// 前序遍历
func PreTraverse(p *RBNode) {
    if p != nil {
        fmt.Printf("%d ", p.key)
        PreTraverse(p.left)
        PreTraverse(p.right)
    }
}

// 中序遍历
func InTraverse(p *RBNode) {
    if p != nil {
        InTraverse(p.left)
        fmt.Printf("%d ", p.key)
        InTraverse(p.right)
    }
}

// 前序遍历
func PostTraverse(p *RBNode) {
    if p != nil {
        PostTraverse(p.left)
        PostTraverse(p.right)
        fmt.Printf("%d ", p.key)
    }
}

3.树的旋转

/* 
 * 对红黑树的节点(x)进行左旋转
 情况1:
 *    x                               y                
 *   /  \      --(左旋)-->           / \                
 *  lx   y                          x  ry     
 *     /   \                       /  \
 *    ly   ry                     lx  ly  
 情况2:
 *      px                              px
 *     /                               /
 *    x                               y                
 *   /  \      --(左旋)-->           / \                
 *  lx   y                          x  ry     
 *     /   \                       /  \
 *    ly   ry                     lx  ly  
 情况3:
 *      px                              px
 *        \                               \
 *         x                               y                
 *        /  \      --(左旋)-->           / \                
 *       lx   y                          x  ry     
 *          /   \                       /  \
 *         ly   ry                     lx  ly  
 *
 */
func left_rotate(root *RBRoot, x *RBNode) {
    var y *RBNode = x.right

    // ly 和 x 的关系
    x.right = y.left
    if y.left != nil {
        y.left.parent = x
    }

    // px 和 y 的关系(要考虑px为空,即x为根节点的情况)
    y.parent = x.parent
    if x.parent == nil {
        root.node = y
    } else {
        if x.parent.left == x {
            x.parent.left = y
        } else {
            x.parent.right = y
        }
    }

    // y 和 x 的关系
    y.left = x
    x.parent = y

}

/* 
 * 对红黑树的节点(y)进行右旋转
 * 情况1:
 *          y                                x                 
 *         /  \      --(右旋)-->            /  \                     
 *        x   ry                           lx   y  
 *       / \                                   / \                   
 *      lx  rx                                rx  ry
 * 情况2:
 *            py                               py
 *           /                                /
 *          y                                x                  
 *         /  \      --(右旋)-->            /  \                     
 *        x   ry                           lx   y  
 *       / \                                   / \                   
 *      lx  rx                                rx  ry
 * 情况3:
 *           py                                py
 *             \                                 \
 *              y                                 x                  
 *             / \      --(右旋)-->               / \                     
 *            x   ry                            lx   y  
 *           / \                                    / \                   
 *         lx  rx                                  rx  ry
 */
func right_rotate(root *RBRoot, y *RBNode) {
    var x *RBNode = y.left

    // rx 和 y 的关系
    y.left = x.right
    if x.right != nil {
        x.right.parent = y
    }

    // py 和 x 的关系(要考虑py为空,即y为根节点的情况)
    x.parent = y.parent
    if y.parent == nil {
        root.node = x
    } else {
        if y.parent.right == y {
            y.parent.right = x
        } else {
            y.parent.left = x
        }
    }

    // y 和 x 的关系
    x.right = y
    y.parent = x
}

4.添加节点

// 添加节点:将节点(node)插入到红黑树中
func Add(root *RBRoot, node *RBNode) {
    var y *RBNode
    var x *RBNode = root.node

    // 找到node应插入位置的父节点
    for x != nil {
        y = x
        if node.key < x.key {
            x = x.left
        } else {
            x = x.right
        }
    }
    // 设置node和父节点的关系
    node.parent = y
    if y != nil {
        if node.key < y.key {
            y.left = node
        } else {
            y.right = node
        }
    } else {
        root.node = node
    }
    // 设置节点为红色
    node.color = RED
    // 修正为红黑树
    add_fixup(root, node)

}

// 红黑树插入修正
func add_fixup(root *RBRoot, node *RBNode) {
    var parent, gparent *RBNode

    // 若“父节点存在,并且父节点的颜色是红色”
    for parent=node.parent; parent != nil && rb_is_red(parent); {
        gparent = parent.parent

        //若“父节点”是“祖父节点的左孩子”
        if parent == gparent.left {
            var uncle *RBNode = gparent.right
            // Case 1条件:叔叔节点是红色
            if uncle != nil && rb_is_red(uncle) {
                rb_set_black(uncle)
                rb_set_black(parent)
                rb_set_red(gparent)
                node = gparent
                continue
            }
            // Case 2条件:叔叔是黑色,且当前节点是右孩子
            if parent.right == node {
                left_rotate(root, parent)
                var tmp *RBNode = parent
                parent = node
                node = tmp
            }
            // Case 3条件:叔叔是黑色,且当前节点是左孩子。
            rb_set_black(parent)
            rb_set_red(gparent)
            right_rotate(root, gparent)
        } else {  
            //若“父节点”是“祖父节点的右孩子”

            var uncle *RBNode = gparent.left
            // Case 1条件:叔叔节点是红色
            if uncle != nil && rb_is_red(uncle) {
                rb_set_black(uncle)
                rb_set_black(parent)
                rb_set_red(gparent)
                node = gparent
                continue
            }
            // Case 2条件:叔叔是黑色,且当前节点是左孩子
            if parent.left == node {
                right_rotate(root, parent)
                var tmp *RBNode = parent
                parent = node
                node = tmp
            }
            // Case 3条件:叔叔是黑色,且当前节点是右孩子。
            rb_set_black(parent)
            rb_set_red(gparent)
            left_rotate(root, gparent)
        }
    }
    // 将根节点设为黑色
    rb_set_black(root.node)
}

5.删除节点

func Delete(root *RBRoot, node *RBNode) {
    var child, parent *RBNode
    var color uint8

    // 被删除节点的"左右孩子都不为空"的情况。
    if node.left != nil && node.right != nil {
        // 获取后继节点
        var replace *RBNode = node.right
        for replace.left != nil {
            replace = replace.left
        }

        // "node节点"不是根节点
        if node.parent != nil {
            if node.parent.left == node {
                node.parent.left = replace
            } else {
                node.parent.right = replace
            }
        } else {
            // "node节点"是根节点,更新根节点。
            root.node = replace
        }
        // child是"取代节点"的右孩子,也是需要"调整的节点"。
        // "取代节点"肯定不存在左孩子!因为它是一个后继节点。
        child = replace.right
        parent = replace.parent
        // 保存"取代节点"的颜色(注意这里删掉的是node节点,但实际删掉的颜色是replace的)
        color = replace.color

        // "被删除节点"是"它的后继节点的父节点"
        if parent == node {
            parent = replace
        } else {
            // child不为空
            if child != nil {
                child.parent = parent
            }
            parent.left = child

            replace.right = node.right
            node.right.parent = replace
        }

        replace.parent = node.parent
        replace.color = node.color
        replace.left = node.left
        node.left.parent = replace

        if color == BLACK {
            delete_fixup(root, child, parent)
        }

        return
    }

    if node.left != nil {
        child = node.left
    } else {
        child = node.right
    }

    parent = node.parent
    color = node.color   // 保存"取代节点"的颜色

    if child != nil {
        child.parent = parent
    }

    // "node节点"不是根节点
    if parent != nil {
        if parent.left == node {
            parent.left = child
        } else {
            parent.right = child
        }
    } else {
        root.node = child
    }

    if color == BLACK {
        delete_fixup(root, child, parent)
    }

}

func delete_fixup(root *RBRoot, node *RBNode, parent *RBNode) {
    var other *RBNode

    for (node == nil || rb_is_black(node)) && node != root.node {
        // node是父节点的左孩子
        if parent.left == node {
            other = parent.right
            // Case 1: node的兄弟节点是红色的  
            if rb_is_red(other) {
                rb_set_black(other)
                rb_set_red(parent)
                left_rotate(root, parent)
                other = parent.right
            }
            // Case 2: node的兄弟w是黑色,且w的俩个孩子也都是黑色的  
            if (other.left == nil || rb_is_black(other.left)) && (other.right == nil || rb_is_black(other.right)) {
                rb_set_red(other)
                node = parent
                parent = node.parent
            } else {
                // Case 3: node的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
                if other.right == nil || rb_is_black(other.right) {
                    rb_set_black(other.left)
                    rb_set_red(other)
                    right_rotate(root, other)
                    other = parent.right
                }
                // Case 4: node的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
                other.color = parent.color
                rb_set_black(parent)
                rb_set_black(other.right)
                left_rotate(root, parent)
                node = root.node
                break
            }
        } else {
            other = parent.left
            // Case 1: node的兄弟w是红色的 
            if rb_is_red(other) {
                rb_set_black(other)
                rb_set_red(parent)
                right_rotate(root, parent)
                other = parent.left
            }
            // Case 2: node的兄弟w是黑色,且w的俩个孩子也都是黑色的  
            if (other.left == nil || rb_is_black(other.left)) && (other.right == nil || rb_is_black(other.right)) {
                rb_set_red(other)
                node = parent
                parent = node.parent
            } else {
                // Case 3: node的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。  
                if other.left == nil || rb_is_black(other.left) {
                    rb_set_black(other.right)
                    rb_set_red(other)
                    left_rotate(root, other)
                    other = parent.left
                }
                // Case 4: node的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
                other.color = parent.color
                rb_set_black(parent)
                rb_set_black(other.left)
                right_rotate(root, parent)
                node = root.node
                break
            }
        }
    }

    if node != nil {
        rb_set_black(node)
    }
}

6.完整代码

package main

import "fmt"


const RED  = 0
const BLACK = 1

type Type int


type RBNode struct {
    color uint8 
    key Type
    left, right, parent *RBNode
}

type RBRoot struct {
    node *RBNode
}

func rb_is_red(node *RBNode) bool {
    return node.color == RED
}

func rb_is_black(node *RBNode) bool {
    return node.color == BLACK
}

func rb_set_red(node *RBNode) {
    node.color = RED
}

func rb_set_black(node *RBNode) {
    node.color = BLACK
}

// 前序遍历
func PreTraverse(p *RBNode) {
    if p != nil {
        fmt.Printf("%d ", p.key)
        PreTraverse(p.left)
        PreTraverse(p.right)
    }
}

// 中序遍历
func InTraverse(p *RBNode) {
    if p != nil {
        InTraverse(p.left)
        fmt.Printf("%d ", p.key)
        InTraverse(p.right)
    }
}

// 前序遍历
func PostTraverse(p *RBNode) {
    if p != nil {
        PostTraverse(p.left)
        PostTraverse(p.right)
        fmt.Printf("%d ", p.key)
    }
}

// 查找键值为key的节点
func Find(node *RBNode, key Type) *RBNode {
    for node != nil && node.key != key {
        if key < node.key {
            node = node.left
        } else {
            node = node.right
        }
    }
    return node
}

// 打印红黑树
func Print(node *RBNode, key Type, direction int) {
    if node != nil {
        if direction == 0 {
            fmt.Printf("%2d(B) is root\n", node.key)
        } else {
            var color, _direction string
            if rb_is_red(node) {
                color = "R"
            } else {
                color = "B"
            }
            if direction == 1 {
                _direction = "right"
            } else {
                _direction = "left"
            }
            // TODO: 这里key 和 %d 的关系
            fmt.Printf("%2d(%s) is %2d's %6s child\n", node.key, color, key, _direction)
        }
        Print(node.left, node.key, -1)
        Print(node.right, node.key, 1)
    }
}

// 打印根节点的所有路径(检测两条红黑树特性)
func PrintRoute(node *RBNode) {
    if node == nil {
        return
    } 
    if node.left == nil && node.right == nil {
        var tmp *RBNode = node
        var num int
        for tmp != nil {
            var color string
            if rb_is_red(tmp) {
                color = "R"
            } else {
                color = "B"
                num++
            }
            fmt.Printf("%2d(%s)-->", tmp.key, color)
            if tmp.parent != nil && (tmp.color == RED && tmp.parent.color == RED) {
                fmt.Println("检测到违反红黑树特性:红节点的子节点是红节点")
            } 
            tmp = tmp.parent
        }
        fmt.Printf("共 %d 个黑节点\n", num)
    }
    PrintRoute(node.left)
    PrintRoute(node.right)
}

/* 
 * 对红黑树的节点(x)进行左旋转
 情况1:
 *    x                               y                
 *   /  \      --(左旋)-->           / \                
 *  lx   y                          x  ry     
 *     /   \                       /  \
 *    ly   ry                     lx  ly  
 情况2:
 *      px                              px
 *     /                               /
 *    x                               y                
 *   /  \      --(左旋)-->           / \                
 *  lx   y                          x  ry     
 *     /   \                       /  \
 *    ly   ry                     lx  ly  
 情况3:
 *      px                              px
 *        \                               \
 *         x                               y                
 *        /  \      --(左旋)-->           / \                
 *       lx   y                          x  ry     
 *          /   \                       /  \
 *         ly   ry                     lx  ly  
 *
 */
func left_rotate(root *RBRoot, x *RBNode) {
    var y *RBNode = x.right

    // ly 和 x 的关系
    x.right = y.left
    if y.left != nil {
        y.left.parent = x
    }

    // px 和 y 的关系(要考虑px为空,即x为根节点的情况)
    y.parent = x.parent
    if x.parent == nil {
        root.node = y
    } else {
        if x.parent.left == x {
            x.parent.left = y
        } else {
            x.parent.right = y
        }
    }

    // y 和 x 的关系
    y.left = x
    x.parent = y

}

/* 
 * 对红黑树的节点(y)进行右旋转
 * 情况1:
 *          y                                x                 
 *         /  \      --(右旋)-->            /  \                     
 *        x   ry                           lx   y  
 *       / \                                   / \                   
 *      lx  rx                                rx  ry
 * 情况2:
 *            py                               py
 *           /                                /
 *          y                                x                  
 *         /  \      --(右旋)-->            /  \                     
 *        x   ry                           lx   y  
 *       / \                                   / \                   
 *      lx  rx                                rx  ry
 * 情况3:
 *           py                                py
 *             \                                 \
 *              y                                 x                  
 *             / \      --(右旋)-->               / \                     
 *            x   ry                            lx   y  
 *           / \                                    / \                   
 *         lx  rx                                  rx  ry
 */
func right_rotate(root *RBRoot, y *RBNode) {
    var x *RBNode = y.left

    // rx 和 y 的关系
    y.left = x.right
    if x.right != nil {
        x.right.parent = y
    }

    // py 和 x 的关系(要考虑py为空,即y为根节点的情况)
    x.parent = y.parent
    if y.parent == nil {
        root.node = x
    } else {
        if y.parent.right == y {
            y.parent.right = x
        } else {
            y.parent.left = x
        }
    }

    // y 和 x 的关系
    x.right = y
    y.parent = x
}

// 添加节点:将节点(node)插入到红黑树中
func Add(root *RBRoot, node *RBNode) {
    var y *RBNode
    var x *RBNode = root.node

    // 找到node应插入位置的父节点
    for x != nil {
        y = x
        if node.key < x.key {
            x = x.left
        } else {
            x = x.right
        }
    }
    // 设置node和父节点的关系
    node.parent = y
    if y != nil {
        if node.key < y.key {
            y.left = node
        } else {
            y.right = node
        }
    } else {
        root.node = node
    }
    // 设置节点为红色
    node.color = RED
    // 修正为红黑树
    add_fixup(root, node)

}

// 红黑树插入修正
func add_fixup(root *RBRoot, node *RBNode) {
    var parent, gparent *RBNode

    // 若“父节点存在,并且父节点的颜色是红色”
    for parent=node.parent; parent != nil && rb_is_red(parent); {
        gparent = parent.parent

        //若“父节点”是“祖父节点的左孩子”
        if parent == gparent.left {
            var uncle *RBNode = gparent.right
            // Case 1条件:叔叔节点是红色
            if uncle != nil && rb_is_red(uncle) {
                rb_set_black(uncle)
                rb_set_black(parent)
                rb_set_red(gparent)
                node = gparent
                continue
            }
            // Case 2条件:叔叔是黑色,且当前节点是右孩子
            if parent.right == node {
                left_rotate(root, parent)
                var tmp *RBNode = parent
                parent = node
                node = tmp
            }
            // Case 3条件:叔叔是黑色,且当前节点是左孩子。
            rb_set_black(parent)
            rb_set_red(gparent)
            right_rotate(root, gparent)
        } else {  
            //若“父节点”是“祖父节点的右孩子”

            var uncle *RBNode = gparent.left
            // Case 1条件:叔叔节点是红色
            if uncle != nil && rb_is_red(uncle) {
                rb_set_black(uncle)
                rb_set_black(parent)
                rb_set_red(gparent)
                node = gparent
                continue
            }
            // Case 2条件:叔叔是黑色,且当前节点是左孩子
            if parent.left == node {
                right_rotate(root, parent)
                var tmp *RBNode = parent
                parent = node
                node = tmp
            }
            // Case 3条件:叔叔是黑色,且当前节点是右孩子。
            rb_set_black(parent)
            rb_set_red(gparent)
            left_rotate(root, gparent)
        }
    }
    // 将根节点设为黑色
    rb_set_black(root.node)
}

func Delete(root *RBRoot, node *RBNode) {
    var child, parent *RBNode
    var color uint8

    // 被删除节点的"左右孩子都不为空"的情况。
    if node.left != nil && node.right != nil {
        // 获取后继节点
        var replace *RBNode = node.right
        for replace.left != nil {
            replace = replace.left
        }

        // "node节点"不是根节点
        if node.parent != nil {
            if node.parent.left == node {
                node.parent.left = replace
            } else {
                node.parent.right = replace
            }
        } else {
            // "node节点"是根节点,更新根节点。
            root.node = replace
        }
        // child是"取代节点"的右孩子,也是需要"调整的节点"。
        // "取代节点"肯定不存在左孩子!因为它是一个后继节点。
        child = replace.right
        parent = replace.parent
        // 保存"取代节点"的颜色(注意这里删掉的是node节点,但实际删掉的颜色是replace的)
        color = replace.color

        // "被删除节点"是"它的后继节点的父节点"
        if parent == node {
            parent = replace
        } else {
            // child不为空
            if child != nil {
                child.parent = parent
            }
            parent.left = child

            replace.right = node.right
            node.right.parent = replace
        }

        replace.parent = node.parent
        replace.color = node.color
        replace.left = node.left
        node.left.parent = replace

        if color == BLACK {
            delete_fixup(root, child, parent)
        }

        return
    }

    if node.left != nil {
        child = node.left
    } else {
        child = node.right
    }

    parent = node.parent
    color = node.color   // 保存"取代节点"的颜色

    if child != nil {
        child.parent = parent
    }

    // "node节点"不是根节点
    if parent != nil {
        if parent.left == node {
            parent.left = child
        } else {
            parent.right = child
        }
    } else {
        root.node = child
    }

    if color == BLACK {
        delete_fixup(root, child, parent)
    }

}

func delete_fixup(root *RBRoot, node *RBNode, parent *RBNode) {
    var other *RBNode

    for (node == nil || rb_is_black(node)) && node != root.node {
        // node是父节点的左孩子
        if parent.left == node {
            other = parent.right
            // Case 1: node的兄弟节点是红色的  
            if rb_is_red(other) {
                rb_set_black(other)
                rb_set_red(parent)
                left_rotate(root, parent)
                other = parent.right
            }
            // Case 2: node的兄弟w是黑色,且w的俩个孩子也都是黑色的  
            if (other.left == nil || rb_is_black(other.left)) && (other.right == nil || rb_is_black(other.right)) {
                rb_set_red(other)
                node = parent
                parent = node.parent
            } else {
                // Case 3: node的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
                if other.right == nil || rb_is_black(other.right) {
                    rb_set_black(other.left)
                    rb_set_red(other)
                    right_rotate(root, other)
                    other = parent.right
                }
                // Case 4: node的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
                other.color = parent.color
                rb_set_black(parent)
                rb_set_black(other.right)
                left_rotate(root, parent)
                node = root.node
                break
            }
        } else {
            other = parent.left
            // Case 1: node的兄弟w是红色的 
            if rb_is_red(other) {
                rb_set_black(other)
                rb_set_red(parent)
                right_rotate(root, parent)
                other = parent.left
            }
            // Case 2: node的兄弟w是黑色,且w的俩个孩子也都是黑色的  
            if (other.left == nil || rb_is_black(other.left)) && (other.right == nil || rb_is_black(other.right)) {
                rb_set_red(other)
                node = parent
                parent = node.parent
            } else {
                // Case 3: node的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。  
                if other.left == nil || rb_is_black(other.left) {
                    rb_set_black(other.right)
                    rb_set_red(other)
                    left_rotate(root, other)
                    other = parent.left
                }
                // Case 4: node的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
                other.color = parent.color
                rb_set_black(parent)
                rb_set_black(other.left)
                right_rotate(root, parent)
                node = root.node
                break
            }
        }
    }

    if node != nil {
        rb_set_black(node)
    }
}


func main() {
    //var datas = []Type{10, 40, 30, 60, 90, 70, 20, 50, 80}
    var datas = []Type{10, 40, 30, 60, 90, 70, 20, 80}
    
    var root *RBRoot = new(RBRoot)
    for _, data := range datas {
        var node = &RBNode{key:data}
        Add(root, node)
    }
    fmt.Print("前序遍历:")
    PreTraverse(root.node)
    fmt.Print("\n中序遍历:")
    InTraverse(root.node)
    fmt.Print("\n后序遍历:")
    PostTraverse(root.node)
    fmt.Print("\n\n")

    Print(root.node, root.node.key, 0)
    fmt.Print("\n")

    var delNode = Find(root.node, 30)
    Delete(root, delNode)
    Print(root.node, root.node.key, 0)
    fmt.Print("\n")
    PrintRoute(root.node)

}
posted @ 2021-11-03 19:44  qxcheng  阅读(214)  评论(0编辑  收藏  举报