golang-redBlackTree-insert

freedbg · 2018-01-14 23:13:32 · 877 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2018-01-14 23:13:32 的主题,其中的信息可能已经有所发展或是发生改变。

package main

import (
    "fmt"
)

func main() {
    fmt.Println("red-black-tree")
    var data = []int{6, 5, 3, 1, 8, 7, 2, 4, 9, 0, 3}
    //var data = []int{6, 5, 3, 1}

    tree := NewTree()
    for _, v := range data {
        tree.insertB(v)
    }
    fmt.Println(tree.size)
}

type node struct {
    l, r, p *node
    v       int
    c       bool //0 = red 1=black
}

type Tree struct {
    root *node
    last *node
    size int
}

func NewTree() *Tree {
    return &Tree{}
}

func (n *node) getGp() *node {
    if n.p == nil {
        return nil
    }
    if n.p.p == nil {
        return nil
    }
    return n.p.p
}

func (n *node) getUn() *node {
    if n.getGp() == nil {
        return nil
    }
    if n.p == n.getGp().l {
        return n.getGp().r
    } else {
        return n.getGp().l
    }
}

// rotate cur node
func (tree *Tree) rotateR(n *node) {
    gp := n.getGp()
    p := n.p
    r := n.r

    n.r = p
    n.p = gp

    if p != nil {
        p.p = n
        p.l = r
        if r != nil {
            r.p = p
        }
    }
    if tree.root == p {
        tree.root = n
    }

    if gp != nil {
        if gp.l == p {
            gp.l = n
        } else {
            gp.r = n
        }
    }
}

func (tree *Tree) rotateL(n *node) {
    gp := n.getGp()
    p := n.p
    l := n.l

    n.l = p
    n.p = gp

    if p != nil {
        p.p = n
        p.r = l
        if l != nil {
            l.p = p
        }
    }

    if tree.root == p {
        tree.root = n
    }

    if gp != nil {
        if gp.l == p {
            gp.l = n
        } else {
            gp.r = n
        }
    }

}

func getMin() {

}

func getMax() {

}

func (tree *Tree) insertB(v int) {
    if tree.root == nil {
        tree.root = new(node)
        tree.root.v = v
        tree.root.c = true
        tree.size++
    }

    if v < tree.root.v {
        if tree.Insert(&tree.root.l, v, tree.root) {
            printT(tree.root)
            tree.size++
            tree.inserCase(tree.last)
        }
    }

    if v > tree.root.v {
        if tree.Insert(&tree.root.r, v, tree.root) {
            printT(tree.root)
            tree.size++
            tree.inserCase(tree.last)
        }
    }
    printT(tree.root)
}

func (tree *Tree) Insert(n **node, v int, fa *node) bool {

    pn := (*n)
    if (*n) == nil {
        (*n) = new(node)
        (*n).v = v
        (*n).p = fa
        tree.last = (*n)
        return true
    }

    if v > pn.v {
        tree.Insert(&(pn.r), v, *n)
    }

    if v < pn.v {
        tree.Insert(&(pn.l), v, *n)
    }

    if v == pn.v {
        return false
    }
    return true
}

func (tree *Tree) inserCase(n *node) {
    if n.p == nil {
        n.c = true
        tree.root = n
        return
    }

    if n.p.c == false {
        if n.getUn() != nil && n.getUn().c == false {
            fmt.Println("aaaaa", n)
            n.p.c = true
            n.getUn().c = true
            n.getGp().c = false
            tree.inserCase(n.getGp()) //if root node
        } else {
            //nil or black
            if n == n.p.r && n.getGp() != nil && n.p == n.getGp().l {
                tree.rotateL(n)
                tree.rotateR(n)
                n.c = true
                n.l.c = false
                n.r.c = false
            }
            if n == n.p.l && n.getGp() != nil && n.p == n.getGp().r {
                tree.rotateR(n)
                tree.rotateL(n)
                n.c = true
                n.l.c = false
                n.r.c = false
            }
            if n == n.p.l && n.getGp() != nil && n.p == n.getGp().l {

                n.p.c = true
                if n.getGp() != nil {
                    n.getGp().c = false
                }
                tree.rotateR(n.p)
            }
            if n == n.p.r && n.getGp() != nil && n.p == n.getGp().r {
                n.p.c = true
                if n.getGp() != nil {
                    n.getGp().c = false
                }
                tree.rotateL(n.p)
            }
        }

    }
}

//test print ----------------------------------------------
var fstr = make([]string, 20, 20)

func printT(tree *node) {
    fmt.Println(tree)
    fstr = make([]string, 8, 8)
    printTree(tree, 0, "")
    for i, str := range fstr {
        fmt.Println("L", i, str)
    }
}

func printTree(tree *node, i int, n string) {
    fmt.Println("-----", tree)
    i++
    str := " "
    for n := i; n < 9; n++ {
        str += "-"
    }
    var tmp string
    if tree.c == true {
        tmp = fmt.Sprintf("%s\033[40;37m [%d] \033[0m%s%s", str, tree.v, n, str)
    } else {
        tmp = fmt.Sprintf("%s\033[41;37m [%d] \033[0m%s%s", str, tree.v, n, str)
    }

    fstr[i] += tmp
    if tree.l != nil {
        printTree(tree.l, i, "L"+fmt.Sprintf("%d", tree.v))
    }
    if tree.r != nil {
        printTree(tree.r, i, "R"+fmt.Sprintf("%d", tree.v))
    }
}

改进了下 BST insert的写法,终于轻松多了


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

877 次点击  
加入收藏 微博
1 回复  |  直到 2018-01-14 23:14:39
freedbg
freedbg · #1 · 7年之前

func (tree Tree) Insert(n **node, v int, fa node) bool 这个函数的 n **node 能不能写的更加简单些

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传