golang 实现二叉搜索树(面向对象,非递归)

二叉搜索树

golang 实现非递归方式的二叉搜索树(OO)。
实现时以index为索引比较,data中记录节点数据。
实现方法:
1. 二叉树中插入节点(Insert);
2. 二叉树中查找节点 (Search);
3. 二叉树中删除节点(Delete) —>需要考虑多种情况: 没有任何子树,只有左或右子树,同时有左子树和右子树

二叉搜索不是平衡树,搜索最坏情况(n),最好情况log(n)

源代码

package main

import (
    "container/list"
    "errors"
    "fmt"
)

var (
    errNotExist       = errors.New("index is not existed")
    errTreeNil        = errors.New("tree is null")
    errTreeIndexExist = errors.New("tree index is existed")
)

type BSTree struct {
    root *Node
}
type Node struct {
    lchild *Node
    rchild *Node
    parent *Node
    index  int
    data   int
}

//查找并返回节点
func (tree *BSTree) Search(index int) (*Node, error) {
    node := tree.root
    for {
        if node == nil {
            return nil, errNotExist
        }
        if index == node.index { //查找到index节点
            return node, nil
        } else if index > node.index {
            node = node.rchild
        } else {
            node = node.lchild
        }
    }
}

func (tree *BSTree) Delete(node *Node) error {
    if node == nil {
        return errNotExist
    }
    //记录查找到的节点
    var n *Node
    if node.lchild == nil && node.rchild == nil {
        n = nil
    } else if node.lchild == nil || node.rchild == nil {
        //如果节点只有左子树或者右子树
        if node.lchild != nil {
            n = node.lchild
        } else {
            n = node.rchild
        }
    } else if node.lchild != nil && node.rchild != nil {
        //如果节点存在左右子树
        n = node.lchild
        //左子树中查找前驱
        for {
            if n.rchild == nil {
                break
            }
            n = n.rchild
        }
        //将前驱从树中剥离出来
        if n.index > n.parent.index {
            n.parent.rchild = nil
        } else {
            n.parent.lchild = nil
        }
        //前驱替换节点
        n.parent = node.parent
        n.lchild = node.lchild
        n.rchild = node.rchild
    }
    if node.parent == nil { //根节点
        tree.root = n
    } else if node.parent.index > node.index {
        node.parent.lchild = n
    } else {
        node.parent.rchild = n
    }
    return nil
}

func (tree *BSTree) Insert(index int, data int) error {
    //当前树为空
    if tree.root == nil {
        tree.root = &Node{lchild: nil, rchild: nil, parent: nil, index: index, data: data}
        return nil
    }
    //将节点放入对应位置
    node := tree.root
    for {
        if node.index == index {
            return errTreeIndexExist
        }
        //找到节点,插入数据
        if node.index > index {
            if node.lchild == nil {
                node.lchild = &Node{lchild: nil, rchild: nil, parent: node, index: index, data: data}
                return nil
            } else {
                node = node.lchild
                break
            }
        }
        if node.index < index {
            if node.rchild == nil {
                node.rchild = &Node{lchild: nil, rchild: nil, parent: node, index: index, data: data}
                return nil
            } else {
                node = node.rchild
                break
            }
        }
    }
    return nil
}

//中序遍历树,并根据钩子函数处理数据
func (tree *BSTree) Midtraverse(handle func(interface{}) error) error {
    //func (tree *BSTree) Midtraverse() error {
    if tree.root == nil {
        return errTreeNil
    }
    l := list.New()
    //入队、压栈  ----> list实现队列功能:push 数据到末尾, get 数据在头部
    l.PushBack(tree.root)
    for {
        e := l.Front()
        if e == nil {
            break
        }
        //container/list 出来的是一个 Element元素,Element的Value是interface{}类型为一个指针,类型转换时需要转换为指针
        node := e.Value.(*Node)
        l.Remove(e)

        if err := handle(node); err != nil {
            return err
        }
        //左节点压栈
        if node.lchild != nil {
            l.PushBack(node.lchild)
        }
        //右子树压栈
        if node.rchild != nil {
            l.PushBack(node.rchild)
        }
    }
    return nil
}

//test
func main() {
    tree := &BSTree{}
    // 插入测试数据
    tree.Insert(3, 6)
    tree.Insert(4, 6)
    tree.Insert(2, 7)
    //打印节点匿名函数
    f := func(node interface{}) error {
        if node.(*Node).parent == nil {
            fmt.Printf("this node is tree root node. node.index:%d node.data:%d\n", node.(*Node).index, node.(*Node).data)
        } else {
            fmt.Printf("node.index:%d node.data:%d node.parent.index:%d\n", node.(*Node).index, node.(*Node).data, node.(*Node).parent.index)
        }
        return nil
    }
    //中序遍历搜索树,打印节点
    if err := tree.Midtraverse(f); err != nil {
        fmt.Printf("Midtraverse failed err:%v\n", err)
    }
    //查找节点节点
    node, err := tree.Search(3)
    if err != nil {
        fmt.Printf("Search failed, err:%v", err)
    } else {
        f(node) //调用匿名函数打印节点
    }
    //删除节点,并中序遍历打印显示
    fmt.Printf("Delete node.index:%d\n", node.index)
    tree.Delete(node)

    if err := tree.Midtraverse(f); err != nil {
        fmt.Printf("Midtraverse failed err:%v\n", err)
    }

}

运行结果

$ go run main.go
this node is tree root node. node.index:3 node.data:6
node.index:2 node.data:7 node.parent.index:3
node.index:4 node.data:6 node.parent.index:3
this node is tree root node. node.index:3 node.data:6
Delete node.index:3
this node is tree root node. node.index:2 node.data:7
node.index:4 node.data:6 node.parent.index:3

你可能感兴趣的:(golang,数据结构)