Golang算法模板-树、二叉树构建和遍历

58 阅读4分钟

树是一个无向无环图,n个节点正好有n-1条边,再任意加上一条边就可以构成回路。

一个结点的上一个结点是这个结点父结点,这个节点是子结点,并且父结点和子结点是相对的。特别的,如果一个结点没有父结点,那这个结点是根节点;一个结点没有子结点,它是叶节点。

二叉树

如果一个树除了叶结点之外的其他每个结点都不多于两个子结点,那么这个树叫二叉树。

从根结点为第一层,依次向下第二层、第三层

特点:

  • 下标从1开始,如果一个结点是i,那么它的左子结点是2*i,它的右子结点是2*i+1
  • 下标从0开始,如果一个节点是i,那么它的左子节点是2*i+1,它的右子节点是2*i+2

大根堆/小根堆

如果一个完全二叉树中任意父结点都比子结点存的数的数值小,这个完全二叉树又叫最小堆,此时这组数据的最小的数就在根节点上。

反之,如果任意父结点都比子结点存的数的数值大,它就叫最大堆,此时最大的数在根节点上。

高度/深度

二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数。

??????

满二叉树

如果除了叶结点外其他每个结点都有两个子节点,这个树就叫满二叉树。

完全二叉树

如果只有最右边几个结点有缺少外其他的节点都有两个子节点(如果一个结点存在右子结点,那就一定有左子结点的情况),它就叫完全二叉树。

二叉搜索(排序)树

该树是一颗二叉树。

如果左子树不为空,则左子树上所有节点的值均小于根节点的值。

如果右子树不为空,则右子树上所有节点的值均大于根节点的值。

左、右子树也都是二叉搜索树。

二叉查找树就是为了快速查找某个元素

二叉搜索(查找)树,也叫二叉排序树

二叉搜索树插入删除元素图解https://blog.csdn.net/cnds123321/article/details/113994581

二叉平衡树

又被称为AVL树,它是一颗空树或左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树。

二叉树遍历

前序遍历

  • 如果二叉树为空,则返回。

  • 如果二叉树不为空,则:

    • 访问根节点。
    • 以前序遍历的方式遍历根节点的左子树。
    • 以前序遍历的方式遍历根节点的右子树。

前序遍历顺序为:A - B - D - H - I - E - C - F - J - G - K

image.png

中序遍历

  • 如果二叉树为空,则返回。

  • 如果二叉树不为空,则:

    • 以中序遍历的方式遍历根节点的左子树。
    • 访问根节点。
    • 以中序遍历的方式遍历根节点的右子树。

中序遍历顺序为:H - D - I - B - E - A - F - J - C - K - G

image.png

后序遍历

  • 如果二叉树为空,则返回。

  • 如果二叉树不为空,则:

    • 以后序遍历的方式遍历根节点的左子树。
    • 以后序遍历的方式遍历根节点的右子树。
    • 访问根节点。

后序遍历顺序为:H - I - D - E - B - J - F - K - G - C - A

image.png

层序遍历

  • 如果二叉树为空,则返回。

  • 如果二叉树不为空,则:

    • 先依次访问二叉树第 1 层的节点。
    • 然后依次访问二叉树第 2 层的节点。
    • ……
    • 依次下去,最后依次访问二叉树最下面一层的节点。

层序遍历顺序为:A - B - C - D - E - F - G - H - I - J - K

image.png

平衡二叉树前中后序遍历

package main
​
import "fmt"type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}
type Tree struct {
    root *TreeNode
}
​
func PreOrder(treeNode *TreeNode) {
    if treeNode != nil {
        fmt.Printf("%d, ", treeNode.Val)
        PreOrder(treeNode.Left)
        PreOrder(treeNode.Right)
    }
}
func InOrder(treeNode *TreeNode) {
    if treeNode != nil {
        InOrder(treeNode.Left)
        fmt.Printf("%d, ", treeNode.Val)
        InOrder(treeNode.Right)
    }
}
func PostOrder(treeNode *TreeNode) {
    if treeNode != nil {
        PostOrder(treeNode.Left)
        PostOrder(treeNode.Right)
        fmt.Printf("%d, ", treeNode.Val)
    }
}
func InsertNode(tree *Tree, val int) {
    var node *TreeNode = &TreeNode{}
    node.Val = val
    node.Left, node.Right = nil, nilif (*tree).root == nil { //非递归构建二叉排序树
        (*tree).root = node
    } else {
        var nodeTemp *TreeNode = (*tree).root
        for nodeTemp != nil {
            if val < nodeTemp.Val {
                if nodeTemp.Left == nil {
                    nodeTemp.Left = node
                    return
                } else {
                    nodeTemp = nodeTemp.Left
                }
            } else {
                if nodeTemp.Right == nil {
                    nodeTemp.Right = node
                    return
                } else {
                    nodeTemp = nodeTemp.Right
                }
            }
        }
    }
}
func main() {
    var tree Tree
    arr := []int{5, 3, 4, 6, 1, 2, 8}
    for _, val := range arr {
        InsertNode(&tree, val)
    }
    PreOrder(tree.root) //5, 3, 1, 2, 4, 6, 8,
    fmt.Printf("\n")
    InOrder(tree.root) //1, 2, 3, 4, 5, 6, 8,
    fmt.Printf("\n")
    PostOrder(tree.root)    //1, 2, 3, 4, 5, 6, 8,
    fmt.Printf("\n")
}