Go语言实现常用算法之树

2019-06-11  本文已影响0人  pyihe
结构定义
type BinaryTreeNode struct {
    Data  interface{}     //数据
    Left  *BinaryTreeNode //左子树
    Right *BinaryTreeNode //右子树
}

func NewTree(data interface{}) *BinaryTreeNode {
    return &BinaryTreeNode{
        Data: data,
    }
}

func (tree *BinaryTreeNode) String() string {
    return fmt.Sprintf(" %v", tree.Data)
}
递归遍历
//前序遍历:以当前节点为根节点,根——>左——>右
func (tree *BinaryTreeNode) PreTraverseRecursion() (treeString string) {

    if tree == nil {
        return
    }

    treeString += tree.String()

    if tree.Left != nil {
        treeString += tree.Left.PreTraverseRecursion()
    }

    if tree.Right != nil {
        treeString += tree.Right.PreTraverseRecursion()
    }
    //fmt.Println(fmt.Sprintf("treeString = [%v]", treeString))
    return
}

//中序遍历:以当前节点为根节点,左——>根——>右
func (tree *BinaryTreeNode) MidTraverseRecursion() (treeString string) {
    if tree == nil {
        return
    }

    if tree.Left != nil {
        treeString += tree.Left.MidTraverseRecursion()
    }

    treeString += tree.String()

    if tree.Right != nil {
        treeString += tree.Right.MidTraverseRecursion()
    }
    //fmt.Println(fmt.Sprintf("treeString = [%v]", treeString))
    return
}

//后续遍历:以当前节点为根节点,左——>右——>根
func (tree *BinaryTreeNode) PostTraverseRecursion() (treeString string) {
    if tree == nil {
        return
    }

    if tree.Left != nil {
        treeString += tree.Left.PostTraverseRecursion()
    }

    if tree.Right != nil {
        treeString += tree.Right.PostTraverseRecursion()
    }

    treeString += tree.String()

    //fmt.Println(fmt.Sprintf("treeString = [%v]", treeString))
    return
}
非递归遍历
栈定义
type Stack struct {
    *list.List
}

//出栈
func (s *Stack) Pop() interface{} {
    if s == nil || s.Len() <= 0 {
        return nil
    }
    value := s.Back()
    s.Remove(value)
    return value.Value
}

//进栈
func (s *Stack) Push(d interface{}) {
    if s == nil {
        return
    }
    s.PushBack(d)
}

//获取栈顶元素
func (s *Stack) Top() interface{} {
    if s == nil {
        return nil
    }
    return s.Back().Value
}
/*  非递归前序遍历
    根——>左——>右
    1、从根节点开始访问,每访问一个元素,执行入栈操作并输出当前节点
    2、访问到最左边的子节点时,开始出栈
    3、每出栈一个元素需要该节点是否存在右节点,如果存在则重复操作1
*/
func (tree *BinaryTreeNode) PreTraverse() (result string) {
    if tree == nil {
        return
    }
    stack := &Stack{
        List: list.New(),
    }

    node := tree
    for node != nil || stack.Len() > 0 {
        if node != nil {
            stack.Push(node)
            result += node.String()
            node = node.Left
        } else {
            node = stack.Pop().(*BinaryTreeNode)
            node = node.Right
        }
    }
    return
}

/*  非递归中序遍历
    左——>根——>右
    1、从根节点开始遍历到最左边的子节点,每访问一个节点就入栈(此处用node访问每个节点)
    2、访问到最左边的子节点时开始出栈,出栈时做输出操作
    3、每次出栈一个元素,需要判断该元素是否存在右节点,如果存在,则重复步骤1
*/
func (tree *BinaryTreeNode) MidTraverse() (result string) {
    if tree == nil {
        return
    }

    stack := &Stack{
        List: list.New(),
    }

    node := tree
    for node != nil || stack.Len() > 0 {
        if node != nil {
            stack.Push(node)
            node = node.Left
        } else {
            node = stack.Pop().(*BinaryTreeNode)
            result += node.String()
            node = node.Right
        }
    }
    return
}

/*  非递归后续遍历
    左——>右——>根
    1、从根节点开始遍历到最左边的子节点,每访问一个节点就入栈(此处用node访问每个节点)
    2、最后一个左子节点入栈后开始出栈操作,出栈时做输出操作
    3、出栈条件:栈顶元素的右子节点为空或者右子节点已经出栈(此处用top纪录当前栈顶元素,last纪录最后出栈的元素)
    4、如果栈顶元素的右子节点不为空且未出栈,则继续步骤1
    为什么要纪录最后出站的元素?
    如果一个节点同时存在左右子节点,按照后序遍历的规则,最后一个出栈元素为一定为该节点的右子节点,此时该节点的子节点已经遍历完,需要将该节点出
    栈并输出
*/
func (tree *BinaryTreeNode) PostTraverse() (result string) {
    if tree == nil {
        return
    }

    stack := &Stack{
        List: list.New(),
    }

    node := tree
    var topNode, lastNode *BinaryTreeNode //top为栈顶元素、last为最后出栈的元素

    for node != nil || stack.Len() > 0 {
        if node != nil {
            stack.Push(node)
            node = node.Left
        } else {
            topNode = stack.Top().(*BinaryTreeNode)
            if topNode.Right == nil || topNode.Right == lastNode {
                stack.Pop()
                result += topNode.String()
                lastNode = topNode
            } else {
                node = topNode.Right
            }
        }
    }
    return
}
//广度优先遍历
func (tree *BinaryTreeNode) LevelTraverse() (result string) {
    if tree == nil {
        return
    }

    treeList := list.New()
    treeList.PushBack(tree)

    for treeList.Len() > 0 {
        element := treeList.Front()
        node := element.Value.(*BinaryTreeNode)

        result += node.String()
        treeList.Remove(element)

        if node.Left != nil {
            treeList.PushBack(node.Left)
        }
        if node.Right != nil {
            treeList.PushBack(node.Right)
        }
    }
    return
}
上一篇 下一篇

猜你喜欢

热点阅读