• go语言|数据结构:二叉树(2)广度和深度搜索


    目录

    创建和追加的优化

    自定义包 biTree

    导入和调用

    广度优先搜索BFS & 深度优先搜索DFS

    广度优先搜索BFS

    深度优先搜索DFS

    遍历二叉树全部叶子结点

    BFS/DFS题目实例

    实例1:层序遍历二叉树成二维数组
    实例2:Z字型层序遍历二叉树成二维数组
    实例3:二叉树从根到叶子的最大深度和最小深度
    实例4:二叉树最下一层的最左边的叶子结点
    实例5:找出二叉树每一层的最大值


    创建和追加的优化

    对Append()和buildTree()的参数作判断,可以是数组也可以单个数据

    要用数组作结点数据域,只能使用appendNode()来创建

    1. package main
    2. import "fmt"
    3. type btNode struct {
    4. Data interface{}
    5. Lchild, Rchild *btNode
    6. }
    7. type biTree struct {
    8. root *btNode
    9. }
    10. func Create(data interface{}) *biTree {
    11. var list []interface{}
    12. btree := &biTree{}
    13. switch data.(type) {
    14. case []interface{}:
    15. list = append(list, data.([]interface{})...)
    16. default:
    17. list = append(list, data)
    18. }
    19. if len(list) > 0 {
    20. btree.root = &btNode{Data: list[0]}
    21. for _, data := range list[1:] {
    22. btree.AppendNode(data)
    23. }
    24. }
    25. return btree
    26. }
    27. func (bt *biTree) Append(data interface{}) {
    28. var list []interface{}
    29. switch data.(type) {
    30. case []interface{}:
    31. list = append(list, data.([]interface{})...)
    32. default:
    33. list = append(list, data)
    34. }
    35. if len(list) > 0 {
    36. for _, data := range list {
    37. bt.AppendNode(data)
    38. }
    39. }
    40. }
    41. func (bt *biTree) AppendNode(data interface{}) {
    42. root := bt.root
    43. if root == nil {
    44. bt.root = &btNode{Data: data}
    45. return
    46. }
    47. Queue := []*btNode{root}
    48. for len(Queue) > 0 {
    49. cur := Queue[0]
    50. Queue = Queue[1:]
    51. if cur.Lchild != nil {
    52. Queue = append(Queue, cur.Lchild)
    53. } else {
    54. cur.Lchild = &btNode{Data: data}
    55. return
    56. }
    57. if cur.Rchild != nil {
    58. Queue = append(Queue, cur.Rchild)
    59. } else {
    60. cur.Rchild = &btNode{Data: data}
    61. break
    62. }
    63. }
    64. }
    65. func (bt *biTree) Levelorder() []interface{} {
    66. var res []interface{}
    67. root := bt.root
    68. if root == nil {
    69. return res
    70. }
    71. Queue := []*btNode{root}
    72. for len(Queue) > 0 {
    73. cur := Queue[0]
    74. Queue = Queue[1:]
    75. res = append(res, cur.Data)
    76. if cur.Lchild != nil {
    77. Queue = append(Queue, cur.Lchild)
    78. }
    79. if cur.Rchild != nil {
    80. Queue = append(Queue, cur.Rchild)
    81. }
    82. }
    83. return res
    84. }
    85. func (bt *biTree) Preorder() []interface{} {
    86. var res []interface{}
    87. cur := bt.root
    88. Stack := []*btNode{}
    89. for cur != nil || len(Stack) > 0 {
    90. for cur != nil {
    91. res = append(res, cur.Data)
    92. Stack = append(Stack, cur)
    93. cur = cur.Lchild
    94. }
    95. if len(Stack) > 0 {
    96. cur = Stack[len(Stack)-1]
    97. Stack = Stack[:len(Stack)-1]
    98. cur = cur.Rchild
    99. }
    100. }
    101. return res
    102. }
    103. func (bt *biTree) Inorder() []interface{} {
    104. var res []interface{}
    105. cur := bt.root
    106. Stack := []*btNode{}
    107. for cur != nil || len(Stack) > 0 {
    108. for cur != nil {
    109. Stack = append(Stack, cur)
    110. cur = cur.Lchild
    111. }
    112. if len(Stack) > 0 {
    113. cur = Stack[len(Stack)-1]
    114. res = append(res, cur.Data)
    115. Stack = Stack[:len(Stack)-1]
    116. cur = cur.Rchild
    117. }
    118. }
    119. return res
    120. }
    121. func (bt *biTree) Postorder() []interface{} {
    122. var res []interface{}
    123. var cur, pre *btNode
    124. Stack := []*btNode{bt.root}
    125. for len(Stack) > 0 {
    126. cur = Stack[len(Stack)-1]
    127. if cur.Lchild == nil && cur.Rchild == nil ||
    128. pre != nil && (pre == cur.Lchild || pre == cur.Rchild) {
    129. res = append(res, cur.Data)
    130. Stack = Stack[:len(Stack)-1]
    131. pre = cur
    132. } else {
    133. if cur.Rchild != nil {
    134. Stack = append(Stack, cur.Rchild)
    135. }
    136. if cur.Lchild != nil {
    137. Stack = append(Stack, cur.Lchild)
    138. }
    139. }
    140. }
    141. return res
    142. }
    143. func main() {
    144. list := []interface{}{1, 2, 3, 4, 5, 6, 7}
    145. tree := &biTree{}
    146. fmt.Println(tree.Preorder())
    147. tree.Append(0)
    148. fmt.Println(tree.Preorder())
    149. tree.Append(1)
    150. fmt.Println(tree.Preorder())
    151. tree = Create(list)
    152. fmt.Println(tree.Preorder())
    153. fmt.Println(tree.Inorder())
    154. fmt.Println(tree.Postorder())
    155. tree.Append("+")
    156. tree.Append("-")
    157. fmt.Println(tree.Inorder())
    158. tree.Append([]interface{}{"A", "B", "C"})
    159. fmt.Println(tree.Preorder())
    160. fmt.Println(tree.Inorder())
    161. fmt.Println(tree.Postorder())
    162. }
    163. /*
    164. []
    165. [0]
    166. [0 1]
    167. [1 2 4 5 3 6 7]
    168. [4 2 5 1 6 3 7]
    169. [4 5 2 6 7 3 1]
    170. [+ 4 - 2 5 1 6 3 7]
    171. [1 2 4 + - 5 A B 3 6 C 7]
    172. [+ 4 - 2 A 5 B 1 C 6 3 7]
    173. [+ - 4 A B 5 2 C 6 7 3 1]
    174. */

    自定义包 biTree

    上面的代码中,去掉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使用了。

    注意:自定义包中的函数和方法命名时一定要首字母大写,否则调用会无法找到。

    导入和调用

    1. package main
    2. import (
    3. "biTree" //导入二叉树自定义包 biTree
    4. "fmt"
    5. )
    6. func main() {
    7. list := []interface{}{1, 2, 3, 4, 5, 6, 7}
    8. tree := biTree.Create(list) //调用自定义包中的函数,需要用“包名称.”作前缀
    9. fmt.Println(tree.Preorder()) //调用方法则不需要前缀,tree就是此包定义的对象
    10. fmt.Println(tree.Inorder())
    11. fmt.Println(tree.Postorder())
    12. fmt.Println(tree.Levelorder())
    13. tree.Append(0)
    14. tree.Append("+")
    15. tree.Append("-")
    16. fmt.Println(tree.Inorder())
    17. tree.Append([]interface{}{"A", "B", "C"})
    18. fmt.Println(tree.Preorder())
    19. fmt.Println(tree.Inorder())
    20. fmt.Println(tree.Postorder())
    21. fmt.Println(tree.Levelorder())
    22. }
    23. /*
    24. [1 2 4 5 3 6 7]
    25. [4 2 5 1 6 3 7]
    26. [4 5 2 6 7 3 1]
    27. [1 2 3 4 5 6 7]
    28. [0 4 + 2 - 5 1 6 3 7]
    29. [1 2 4 0 + 5 - A 3 6 B C 7]
    30. [0 4 + 2 - 5 A 1 B 6 C 3 7]
    31. [0 + 4 - A 5 2 B C 6 7 3 1]
    32. [1 2 3 4 5 6 7 0 + - A B C]
    33. */

    广度优先搜索BFS & 深度优先搜索DFS

    是连通图等图结构的一种遍历算法原型,而树也可以看作是一种没用环的特殊图结构。

    广度优先搜索BFS

    Breath First Search,也称宽度优先搜索,缩写BFS。也即先横向再纵向的搜索,BFS使用队列来实现。BFS就是上一集中写的层序遍历Levelorder(),层序遍历即广度优先。

    深度优先搜索DFS

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

    遍历二叉树全部叶子结点

    递归法:

    1. func (bt *btNode) leaves() []interface{} {
    2. var res []interface{}
    3. if bt != nil {
    4. if bt.Lchild == nil && bt.Rchild == nil {
    5. res = append(res, bt.Data)
    6. }
    7. res = append(res, bt.Lchild.leaves()...)
    8. res = append(res, bt.Rchild.leaves()...)
    9. }
    10. return res
    11. }

    广度优先BFS:

    1. func (bt *biTree) LeafNodeBFS() []interface{} {
    2. var res []interface{}
    3. root := bt.root
    4. if root == nil {
    5. return res
    6. }
    7. Queue := []*btNode{root}
    8. for len(Queue) > 0 {
    9. cur := Queue[0]
    10. Queue = Queue[1:]
    11. if cur.Lchild == nil && cur.Rchild == nil {
    12. res = append(res, cur.Data)
    13. }
    14. if cur.Lchild != nil {
    15. Queue = append(Queue, cur.Lchild)
    16. }
    17. if cur.Rchild != nil {
    18. Queue = append(Queue, cur.Rchild)
    19. }
    20. }
    21. return res
    22. }

    深度优先DFS:

    1. func (bt *biTree) LeafNodeDFS() []interface{} {
    2. var res []interface{}
    3. cur := bt.root
    4. Stack := []*btNode{}
    5. for cur != nil || len(Stack) > 0 {
    6. for cur != nil {
    7. if cur.Lchild == nil && cur.Rchild == nil {
    8. res = append(res, cur.Data)
    9. }
    10. Stack = append(Stack, cur)
    11. cur = cur.Lchild
    12. }
    13. if len(Stack) > 0 {
    14. cur = Stack[len(Stack)-1]
    15. Stack = Stack[:len(Stack)-1]
    16. cur = cur.Rchild
    17. }
    18. }
    19. return res
    20. }

    BFS/DFS题目实例

    实例1:层序遍历二叉树成二维数组

    (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 7

    return 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备用:

    1. func (bt *biTree) BForder2D() [][]interface{} {
    2. var res [][]interface{}
    3. root := bt.root
    4. if root == nil {
    5. return res
    6. }
    7. Queue := []*btNode{root}
    8. for len(Queue) > 0 {
    9. Nodes := []interface{}{}
    10. Levels := len(Queue)
    11. for Levels > 0 {
    12. cur := Queue[0]
    13. Queue = Queue[1:]
    14. Nodes = append(Nodes, cur.Data)
    15. Levels--
    16. if cur.Lchild != nil {
    17. Queue = append(Queue, cur.Lchild)
    18. }
    19. if cur.Rchild != nil {
    20. Queue = append(Queue, cur.Rchild)
    21. }
    22. }
    23. res = append(res, Nodes)
    24. }
    25. return res
    26. }

    遍历过程如以下动图:

    测试代码:

    1. package main
    2. import (
    3. "biTree" //导入二叉树自定义包 biTree
    4. "fmt"
    5. )
    6. func main() {
    7. list1 := []interface{}{1, 2, 4, 5, 6}
    8. list2 := []interface{}{3, 9, 20, 15, 7}
    9. tree := biTree.Create(list1)
    10. fmt.Println(tree.BForder2D())
    11. tree = biTree.Create(list2)
    12. fmt.Println(tree.BForder2D())
    13. }
    14. /*
    15. [[1] [2 4] [5 6]]
    16. [[3] [9 20] [15 7]]
    17. */

    注意:代码遍历方法是正确的,但是题目给定的数组是 [3,9,20,null,null,15,7],而Create()函数按层再从左到右添加结点的,它创建的是一个完全二叉树。需要增加对数据域的类型判断,空值在Go语言中用nil表示,在遍历数组时碰到nil值,则跳过创建此结点,这样就可以创建一个非完全二叉树。另外存在没法创建的可能,比如: {1, nil, nil, 2, 3},要么忽略要么抛出错误。

    改进后的创建代码Build()函数,放进biTree.go,以备调用。

    1. func Build(data interface{}) *biTree {
    2. var list []interface{}
    3. if data == nil {
    4. return &biTree{}
    5. }
    6. switch data.(type) {
    7. case []interface{}:
    8. list = append(list, data.([]interface{})...)
    9. default:
    10. list = append(list, data)
    11. }
    12. if len(list) == 0 {
    13. return &biTree{}
    14. }
    15. node := &btNode{Data: list[0]}
    16. list = list[1:]
    17. Queue := []*btNode{node}
    18. for len(list) > 0 {
    19. if len(Queue) == 0 {
    20. //panic("Given array can not build binary tree.")
    21. //for example: {1, nil, nil, 2, 3}
    22. return &biTree{root: node}
    23. }
    24. cur := Queue[0]
    25. val := list[0]
    26. Queue = Queue[1:]
    27. if val != nil {
    28. cur.Lchild = &btNode{Data: val}
    29. if cur.Lchild != nil {
    30. Queue = append(Queue, cur.Lchild)
    31. }
    32. }
    33. list = list[1:]
    34. if len(list) > 0 {
    35. val := list[0]
    36. if data != nil {
    37. cur.Rchild = &btNode{Data: val}
    38. if cur.Rchild != nil {
    39. Queue = append(Queue, cur.Rchild)
    40. }
    41. }
    42. list = list[1:]
    43. }
    44. }
    45. return &biTree{root: node}
    46. }

    测试代码:

    1. package main
    2. import (
    3. "biTree" //导入二叉树自定义包 biTree
    4. "fmt"
    5. )
    6. func main() {
    7. list := []interface{}{3, 9, 20, nil, nil, 15, 7}
    8. tree := biTree.Build(list)
    9. fmt.Println(tree.BForder2D())
    10. fmt.Println(tree.Levelorder())
    11. fmt.Println(tree.Preorder())
    12. fmt.Println(tree.Inorder())
    13. fmt.Println(tree.Postorder())
    14. list = []interface{}{3, 9, 20, 15, 7}
    15. tree = biTree.Build(list)
    16. fmt.Println(tree.BForder2D())
    17. fmt.Println(tree.Levelorder())
    18. fmt.Println(tree.Preorder())
    19. fmt.Println(tree.Inorder())
    20. fmt.Println(tree.Postorder())
    21. }
    22. /*
    23. [[3] [9 20] [15 7]]
    24. [3 9 20 15 7]
    25. [3 9 20 15 7]
    26. [9 3 15 20 7]
    27. [9 15 7 20 3]
    28. [[3] [9 20] [15 7]]
    29. [3 9 20 15 7]
    30. [3 9 15 7 20]
    31. [15 9 7 3 20]
    32. [15 7 9 20 3]
    33. */

    实例2:Z字型层序遍历二叉树成二维数组

    (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 7

    return its zigzag level order traversal as:

    [
    [3],
    [20,9],
    [15,7]
    ]

    实例3:二叉树从根到叶子的最大深度和最小深度

    (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

    实例4:二叉树最下一层的最左边的叶子结点

    (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.

    实例5:找出二叉树每一层的最大值

    (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]


  • 相关阅读:
    剑指 Offer 13. 机器人的运动范围
    YOLOv8改进 | 2023 | InnerIoU、InnerSIoU、InnerWIoU、FoucsIoU等损失函数
    mac的Jupyter怎么使用
    WPS相关使用
    如何公网远程访问本地群晖NAS File Station文件夹
    国学短剧《我是小影星》栏目火热开拍
    老板让你Excel统计数据无从下手?没事,ChatGPT来帮你!
    VCS工具学习笔记(6)
    搭建zerotier planet服务
    微信小程序ios下,border显示不全兼容问题解决
  • 原文地址:https://blog.csdn.net/boysoft2002/article/details/126556516