
目录
实例1:层序遍历二叉树成二维数组
实例2:Z字型层序遍历二叉树成二维数组
实例3:二叉树从根到叶子的最大深度和最小深度
实例4:二叉树最下一层的最左边的叶子结点
实例5:找出二叉树每一层的最大值
对Append()和buildTree()的参数作判断,可以是数组也可以单个数据
要用数组作结点数据域,只能使用appendNode()来创建
- package main
-
- import "fmt"
-
- type btNode struct {
- Data interface{}
- Lchild, Rchild *btNode
- }
-
- type biTree struct {
- root *btNode
- }
-
- func Create(data interface{}) *biTree {
- var list []interface{}
- btree := &biTree{}
- switch data.(type) {
- case []interface{}:
- list = append(list, data.([]interface{})...)
- default:
- list = append(list, data)
- }
- if len(list) > 0 {
- btree.root = &btNode{Data: list[0]}
- for _, data := range list[1:] {
- btree.AppendNode(data)
- }
- }
- return btree
- }
-
- func (bt *biTree) Append(data interface{}) {
- var list []interface{}
- switch data.(type) {
- case []interface{}:
- list = append(list, data.([]interface{})...)
- default:
- list = append(list, data)
- }
- if len(list) > 0 {
- for _, data := range list {
- bt.AppendNode(data)
- }
- }
- }
-
- func (bt *biTree) AppendNode(data interface{}) {
- root := bt.root
- if root == nil {
- bt.root = &btNode{Data: data}
- return
- }
- Queue := []*btNode{root}
- for len(Queue) > 0 {
- cur := Queue[0]
- Queue = Queue[1:]
- if cur.Lchild != nil {
- Queue = append(Queue, cur.Lchild)
- } else {
- cur.Lchild = &btNode{Data: data}
- return
- }
- if cur.Rchild != nil {
- Queue = append(Queue, cur.Rchild)
- } else {
- cur.Rchild = &btNode{Data: data}
- break
- }
- }
- }
-
- func (bt *biTree) Levelorder() []interface{} {
- var res []interface{}
- root := bt.root
- if root == nil {
- return res
- }
- Queue := []*btNode{root}
- for len(Queue) > 0 {
- cur := Queue[0]
- Queue = Queue[1:]
- res = append(res, cur.Data)
- if cur.Lchild != nil {
- Queue = append(Queue, cur.Lchild)
- }
- if cur.Rchild != nil {
- Queue = append(Queue, cur.Rchild)
- }
- }
- return res
- }
-
- func (bt *biTree) Preorder() []interface{} {
- var res []interface{}
- cur := bt.root
- Stack := []*btNode{}
- for cur != nil || len(Stack) > 0 {
- for cur != nil {
- res = append(res, cur.Data)
- Stack = append(Stack, cur)
- cur = cur.Lchild
- }
- if len(Stack) > 0 {
- cur = Stack[len(Stack)-1]
- Stack = Stack[:len(Stack)-1]
- cur = cur.Rchild
- }
- }
- return res
- }
-
- func (bt *biTree) Inorder() []interface{} {
- var res []interface{}
- cur := bt.root
- Stack := []*btNode{}
- for cur != nil || len(Stack) > 0 {
- for cur != nil {
- Stack = append(Stack, cur)
- cur = cur.Lchild
- }
- if len(Stack) > 0 {
- cur = Stack[len(Stack)-1]
- res = append(res, cur.Data)
- Stack = Stack[:len(Stack)-1]
- cur = cur.Rchild
- }
- }
- return res
- }
-
- func (bt *biTree) Postorder() []interface{} {
- var res []interface{}
- var cur, pre *btNode
- Stack := []*btNode{bt.root}
- for len(Stack) > 0 {
- cur = Stack[len(Stack)-1]
- if cur.Lchild == nil && cur.Rchild == nil ||
- pre != nil && (pre == cur.Lchild || pre == cur.Rchild) {
- res = append(res, cur.Data)
- Stack = Stack[:len(Stack)-1]
- pre = cur
- } else {
- if cur.Rchild != nil {
- Stack = append(Stack, cur.Rchild)
- }
- if cur.Lchild != nil {
- Stack = append(Stack, cur.Lchild)
- }
- }
- }
- return res
- }
-
- func main() {
-
- list := []interface{}{1, 2, 3, 4, 5, 6, 7}
-
- tree := &biTree{}
- fmt.Println(tree.Preorder())
- tree.Append(0)
- fmt.Println(tree.Preorder())
- tree.Append(1)
- fmt.Println(tree.Preorder())
-
- tree = Create(list)
- fmt.Println(tree.Preorder())
- fmt.Println(tree.Inorder())
- fmt.Println(tree.Postorder())
-
- tree.Append("+")
- tree.Append("-")
- fmt.Println(tree.Inorder())
- tree.Append([]interface{}{"A", "B", "C"})
- fmt.Println(tree.Preorder())
- fmt.Println(tree.Inorder())
- fmt.Println(tree.Postorder())
-
- }
-
- /*
- []
- [0]
- [0 1]
- [1 2 4 5 3 6 7]
- [4 2 5 1 6 3 7]
- [4 5 2 6 7 3 1]
- [+ 4 - 2 5 1 6 3 7]
- [1 2 4 + - 5 A B 3 6 C 7]
- [+ 4 - 2 A 5 B 1 C 6 3 7]
- [+ - 4 A B 5 2 C 6 7 3 1]
- */
上面的代码中,去掉import "fmt"一行 及 main()函数全部,package main替换成 package biTree,然后另存为 biTree.go。
接下来在DOS窗口用set gopath查看GOPATH变量,我的电脑返回:
C:\Users\admin>set gopath
GOPATH=C:\Users\admin\go;d:\GOsrc
在gopath的任一路径下新建一个src文件夹,再在src下新建biTree文件夹,最后把biTree.go存放到此文件夹下,就能导入import使用了。
注意:自定义包中的函数和方法命名时一定要首字母大写,否则调用会无法找到。
- package main
-
- import (
- "biTree" //导入二叉树自定义包 biTree
- "fmt"
- )
-
- func main() {
-
- list := []interface{}{1, 2, 3, 4, 5, 6, 7}
-
- tree := biTree.Create(list) //调用自定义包中的函数,需要用“包名称.”作前缀
- fmt.Println(tree.Preorder()) //调用方法则不需要前缀,tree就是此包定义的对象
- fmt.Println(tree.Inorder())
- fmt.Println(tree.Postorder())
- fmt.Println(tree.Levelorder())
-
- tree.Append(0)
- tree.Append("+")
- tree.Append("-")
- fmt.Println(tree.Inorder())
- tree.Append([]interface{}{"A", "B", "C"})
- fmt.Println(tree.Preorder())
- fmt.Println(tree.Inorder())
- fmt.Println(tree.Postorder())
- fmt.Println(tree.Levelorder())
-
- }
-
- /*
- [1 2 4 5 3 6 7]
- [4 2 5 1 6 3 7]
- [4 5 2 6 7 3 1]
- [1 2 3 4 5 6 7]
- [0 4 + 2 - 5 1 6 3 7]
- [1 2 4 0 + 5 - A 3 6 B C 7]
- [0 4 + 2 - 5 A 1 B 6 C 3 7]
- [0 + 4 - A 5 2 B C 6 7 3 1]
- [1 2 3 4 5 6 7 0 + - A B C]
- */
是连通图等图结构的一种遍历算法原型,而树也可以看作是一种没用环的特殊图结构。
Breath First Search,也称宽度优先搜索,缩写BFS。也即先横向再纵向的搜索,BFS使用队列来实现。BFS就是上一集中写的层序遍历Levelorder(),层序遍历即广度优先。

Depth First Search,缩写DFS。也即先纵向再横向的搜索,DFS使用栈来实现。DFS就是上一集中写的先序遍历Preorder(),可认为先序遍历即深度优先。

递归法:
- func (bt *btNode) leaves() []interface{} {
- var res []interface{}
- if bt != nil {
- if bt.Lchild == nil && bt.Rchild == nil {
- res = append(res, bt.Data)
- }
- res = append(res, bt.Lchild.leaves()...)
- res = append(res, bt.Rchild.leaves()...)
- }
- return res
- }
广度优先BFS:
- func (bt *biTree) LeafNodeBFS() []interface{} {
- var res []interface{}
- root := bt.root
- if root == nil {
- return res
- }
- Queue := []*btNode{root}
- for len(Queue) > 0 {
- cur := Queue[0]
- Queue = Queue[1:]
- if cur.Lchild == nil && cur.Rchild == nil {
- res = append(res, cur.Data)
- }
- if cur.Lchild != nil {
- Queue = append(Queue, cur.Lchild)
- }
- if cur.Rchild != nil {
- Queue = append(Queue, cur.Rchild)
- }
- }
- return res
- }
深度优先DFS:
- func (bt *biTree) LeafNodeDFS() []interface{} {
- var res []interface{}
- cur := bt.root
- Stack := []*btNode{}
- for cur != nil || len(Stack) > 0 {
- for cur != nil {
- if cur.Lchild == nil && cur.Rchild == nil {
- res = append(res, cur.Data)
- }
- Stack = append(Stack, cur)
- cur = cur.Lchild
- }
- if len(Stack) > 0 {
- cur = Stack[len(Stack)-1]
- Stack = Stack[:len(Stack)-1]
- cur = cur.Rchild
- }
- }
- return res
- }
(leetcode102#) Binary Tree Level Order Traversal
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).
For Example:
Given binary tree [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7return its level order traversal as:
[
[3],
[9,20],
[15,7]
](leetcode107#) Binary Tree Level Order Traversal II
102题的结果倒序,返回[[3],[9,20],[15,7]],代码略。
遍历代码如下,把它写进biTree.go备用:
- func (bt *biTree) BForder2D() [][]interface{} {
- var res [][]interface{}
- root := bt.root
- if root == nil {
- return res
- }
- Queue := []*btNode{root}
- for len(Queue) > 0 {
- Nodes := []interface{}{}
- Levels := len(Queue)
- for Levels > 0 {
- cur := Queue[0]
- Queue = Queue[1:]
- Nodes = append(Nodes, cur.Data)
- Levels--
- if cur.Lchild != nil {
- Queue = append(Queue, cur.Lchild)
- }
- if cur.Rchild != nil {
- Queue = append(Queue, cur.Rchild)
- }
- }
- res = append(res, Nodes)
- }
- return res
- }
遍历过程如以下动图:

测试代码:
- package main
-
- import (
- "biTree" //导入二叉树自定义包 biTree
- "fmt"
- )
-
- func main() {
-
- list1 := []interface{}{1, 2, 4, 5, 6}
- list2 := []interface{}{3, 9, 20, 15, 7}
-
- tree := biTree.Create(list1)
- fmt.Println(tree.BForder2D())
-
- tree = biTree.Create(list2)
- fmt.Println(tree.BForder2D())
-
- }
-
- /*
- [[1] [2 4] [5 6]]
- [[3] [9 20] [15 7]]
- */
注意:代码遍历方法是正确的,但是题目给定的数组是 [3,9,20,null,null,15,7],而Create()函数按层再从左到右添加结点的,它创建的是一个完全二叉树。需要增加对数据域的类型判断,空值在Go语言中用nil表示,在遍历数组时碰到nil值,则跳过创建此结点,这样就可以创建一个非完全二叉树。另外存在没法创建的可能,比如: {1, nil, nil, 2, 3},要么忽略要么抛出错误。
改进后的创建代码Build()函数,放进biTree.go,以备调用。
- func Build(data interface{}) *biTree {
- var list []interface{}
- if data == nil {
- return &biTree{}
- }
- switch data.(type) {
- case []interface{}:
- list = append(list, data.([]interface{})...)
- default:
- list = append(list, data)
- }
- if len(list) == 0 {
- return &biTree{}
- }
- node := &btNode{Data: list[0]}
- list = list[1:]
- Queue := []*btNode{node}
- for len(list) > 0 {
- if len(Queue) == 0 {
- //panic("Given array can not build binary tree.")
- //for example: {1, nil, nil, 2, 3}
- return &biTree{root: node}
- }
- cur := Queue[0]
- val := list[0]
- Queue = Queue[1:]
- if val != nil {
- cur.Lchild = &btNode{Data: val}
- if cur.Lchild != nil {
- Queue = append(Queue, cur.Lchild)
- }
- }
- list = list[1:]
- if len(list) > 0 {
- val := list[0]
- if data != nil {
- cur.Rchild = &btNode{Data: val}
- if cur.Rchild != nil {
- Queue = append(Queue, cur.Rchild)
- }
- }
- list = list[1:]
- }
- }
- return &biTree{root: node}
- }
测试代码:
- package main
-
- import (
- "biTree" //导入二叉树自定义包 biTree
- "fmt"
- )
-
- func main() {
-
- list := []interface{}{3, 9, 20, nil, nil, 15, 7}
-
- tree := biTree.Build(list)
- fmt.Println(tree.BForder2D())
-
- fmt.Println(tree.Levelorder())
- fmt.Println(tree.Preorder())
- fmt.Println(tree.Inorder())
- fmt.Println(tree.Postorder())
-
- list = []interface{}{3, 9, 20, 15, 7}
- tree = biTree.Build(list)
- fmt.Println(tree.BForder2D())
-
- fmt.Println(tree.Levelorder())
- fmt.Println(tree.Preorder())
- fmt.Println(tree.Inorder())
- fmt.Println(tree.Postorder())
- }
-
- /*
- [[3] [9 20] [15 7]]
- [3 9 20 15 7]
- [3 9 20 15 7]
- [9 3 15 20 7]
- [9 15 7 20 3]
- [[3] [9 20] [15 7]]
- [3 9 20 15 7]
- [3 9 15 7 20]
- [15 9 7 3 20]
- [15 7 9 20 3]
- */
(leetcode103#) Binary Tree Zigzag Level Order Traversal
Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).
For Example:
Given binary tree [3,9,20,null,null,15,7],3
/ \
9 20
/ \
15 7return its zigzag level order traversal as:
[
[3],
[20,9],
[15,7]
]
(leetcode104#) Maximum Depth of Binary Tree
Given a binary tree, find its maximum depth.
The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
Note: A leaf is a node with no children.
(leetcode111#) Minimum Depth of Binary Tree
(leetcode513#) Find Bottom Left Tree Value
Given a binary tree, find the leftmost value in the last row of the tree.
Example 1:
Input:
2
/ \
1 3
Output:
1
Example 2:
Input:
1
/ \
2 3
/ / \
4 5 6
/
7
Output:
7
Note: You may assume the tree (i.e., the given root node) is not NULL.
(leetcode 515#) Find Largest Value in Each Tree Row
You need to find the largest value in each row of a binary tree.
Example:
Input:
1
/ \
3 2
/ \ \
5 3 9
Output: [1, 3, 9]