• go语言|数据结构:二叉树(1)创建与遍历方法


    树 Tree

    树是有限结点组成一个具有层次关系的集合。

    开始写代码前,先复习一遍基本概念:

    名词术语

    结点 Node

    也有写作“节点”,组成树的集合中的“元素”。

    根结点 Root

    没有前驱的结点叫做根结点

    结点的度 Node degree

    一个结点含有子树的个数

    树的度 Tree degree

    所有结点的度最大的那一个叫做树的度

    叶子结点 Leaf

    度为0的结点

    结点的层次 Level

    根为第一层,根的子节点为第二层,依次往下推

    深度 Depth

    树的总层数,就是高度树的高度Height

    二叉树 Binary Tree

    一种特殊的树,是结点的一个有限集合,且所有结点最多有2个子结点,即度只能是0,1,2。

    满二叉树 Full Binary Tree

    除叶子结点外,每一层上的所有结点都有两个子结点二叉树。它的每一个层次的结点数目都达到了最大值。
    结点总数M 和 总层数N 满足: M = 2^N - 1
    每层结点数m 和 层数n 满足: m = 2^(n-1)

    完全二叉树 Complete Binary Tree

    二叉树的叶节点只出现在最下层和次下层,并且最下层的结点都集中在该层的最左边。

    性质

    (1) 在二叉树中,第i层的结点总数不超过2^(i-1);

    (2) 深度为h的二叉树最多有2^h-1个结点(h>=1),最少有h个结点;

    (3) 对于任意一棵二叉树,其所有的叶结点数为:N0,而度为2的所有结点的数量为:N2,则:N0=N2+1,请观察上图;

    (4) 具有n个结点的完全二叉树的深度为int(log2n)+1

    (5)有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:

    若I为结点编号则 如果I<>1,则其父结点的编号为I/2;

    如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;

    如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。

    (6) 给定N个节点,能构成h(N)种不同的二叉树。h(N)为卡特兰数的第N项。h(n)=C(n,2*n)/(n+1)。


    二叉树的创建

    结点

    数据域 Data,使用 interface{} 好处是可以添加任意类型的数据结点

    左、右子树结点指针 Lchild, Rchild

    1. type btNode struct {
    2. Data interface{}
    3. Lchild *btNode
    4. Rchild *btNode
    5. }

    二叉树

    1. type biTree struct {
    2. root *btNode
    3. }

    创建与访问

    1. package main
    2. import "fmt"
    3. type btNode struct {
    4. Data interface{}
    5. Lchild *btNode
    6. Rchild *btNode
    7. }
    8. type biTree struct {
    9. root *btNode
    10. }
    11. func main() {
    12. var tree *biTree
    13. var node1, node2, node3, node4 *btNode
    14. tree = new(biTree)
    15. node1 = &btNode{Data: 1}
    16. node2 = &btNode{Data: 2}
    17. node3 = &btNode{Data: 3}
    18. node4 = &btNode{Data: 4}
    19. tree.root = node1
    20. node1.Lchild = node2
    21. node1.Rchild = node3
    22. node2.Lchild = node4
    23. fmt.Println(tree.root.Data)
    24. fmt.Println(tree.root.Lchild.Data)
    25. fmt.Println(tree.root.Rchild.Data)
    26. fmt.Println(tree.root.Lchild.Lchild.Data)
    27. }
    28. /*
    29. 1
    30. 2
    31. 3
    32. 4
    33. */

    用数组批量创建结点

    1. package main
    2. import "fmt"
    3. type btNode struct {
    4. Data interface{}
    5. Lchild *btNode
    6. Rchild *btNode
    7. }
    8. type biTree struct {
    9. root *btNode
    10. }
    11. func NewTree() *biTree {
    12. return &biTree{}
    13. }
    14. func newTreeNode(data interface{}) *btNode {
    15. return &btNode{
    16. Data: data,
    17. Lchild: nil,
    18. Rchild: nil,
    19. }
    20. }
    21. func main() {
    22. list := []interface{}{1, 2, 3, 4, 5, 6}
    23. node := []*btNode{}
    24. tree := NewTree()
    25. for _, data := range list {
    26. node = append(node, newTreeNode(data))
    27. }
    28. tree.root = node[0]
    29. tree.root.Lchild = node[1]
    30. tree.root.Rchild = node[2]
    31. tree.root.Lchild.Lchild = node[3]
    32. tree.root.Lchild.Rchild = node[4]
    33. tree.root.Rchild.Lchild = node[5]
    34. fmt.Println(tree.root.Data)
    35. fmt.Println(tree.root.Lchild.Data)
    36. fmt.Println(tree.root.Rchild.Data)
    37. fmt.Println(tree.root.Lchild.Lchild.Data)
    38. fmt.Println(tree.root.Lchild.Rchild.Data)
    39. fmt.Println(tree.root.Rchild.Lchild.Data)
    40. }
    41. /*
    42. 1
    43. 2
    44. 3
    45. 4
    46. 5
    47. 6
    48. */

    追加结点

    从上到下逐层且每一层从左到右访问二叉树,遇到首个空结点时就添加一结点。

    1. package main
    2. import "fmt"
    3. type btNode struct {
    4. Data interface{}
    5. Lchild *btNode
    6. Rchild *btNode
    7. }
    8. type biTree struct {
    9. root *btNode
    10. }
    11. func NewTree() *biTree {
    12. return &biTree{}
    13. }
    14. func newTreeNode(data interface{}) *btNode {
    15. return &btNode{
    16. Data: data,
    17. Lchild: nil,
    18. Rchild: nil,
    19. }
    20. }
    21. func (bt *biTree) appendNode(data interface{}) {
    22. cur := bt.root
    23. if cur == nil { //空树则创建一个根结点
    24. bt.root = newTreeNode(data)
    25. return
    26. }
    27. Queue := []*btNode{cur}
    28. for len(Queue) > 0 {
    29. cur := Queue[0]
    30. Queue = Queue[1:]
    31. if cur.Lchild != nil {
    32. Queue = append(Queue, cur.Lchild)
    33. } else {
    34. cur.Lchild = newTreeNode(data)
    35. return
    36. }
    37. if cur.Rchild != nil {
    38. Queue = append(Queue, cur.Rchild)
    39. } else {
    40. cur.Rchild = newTreeNode(data)
    41. break
    42. }
    43. }
    44. }
    45. func main() {
    46. tree := &biTree{}
    47. list := []interface{}{1, 2, 3, 4, 5, 6}
    48. for _, data := range list {
    49. tree.appendNode(data)
    50. }
    51. fmt.Println(tree.root.Data)
    52. fmt.Println(tree.root.Lchild.Data)
    53. fmt.Println(tree.root.Rchild.Data)
    54. fmt.Println(tree.root.Lchild.Lchild.Data)
    55. fmt.Println(tree.root.Lchild.Rchild.Data)
    56. fmt.Println(tree.root.Rchild.Lchild.Data)
    57. tree.appendNode(0)
    58. fmt.Println(tree.root.Rchild.Rchild.Data)
    59. }
    60. /*
    61. 1
    62. 2
    63. 3
    64. 4
    65. 5
    66. 6
    67. 0
    68. */

    追加结点时的访问方法称为“层序”,层序访问整个二叉树只要把代码中追加结点的语句换成打印所有结点的数据域,即完成了二叉树的“层序遍历”:

    1. package main
    2. import "fmt"
    3. type btNode struct {
    4. Data interface{}
    5. Lchild *btNode
    6. Rchild *btNode
    7. }
    8. type biTree struct {
    9. root *btNode
    10. }
    11. func NewTree() *biTree {
    12. return &biTree{}
    13. }
    14. func newTreeNode(data interface{}) *btNode {
    15. return &btNode{
    16. Data: data,
    17. Lchild: nil,
    18. Rchild: nil,
    19. }
    20. }
    21. func levelorderPrint(bt *biTree) {
    22. cur := bt.root
    23. if cur == nil {
    24. fmt.Print("Empty Binary Tree")
    25. }
    26. Queue := []*btNode{cur}
    27. for len(Queue) > 0 {
    28. cur := Queue[0]
    29. Queue = Queue[1:]
    30. fmt.Print(cur.Data, " ")
    31. if cur.Lchild != nil {
    32. Queue = append(Queue, cur.Lchild)
    33. }
    34. if cur.Rchild != nil {
    35. Queue = append(Queue, cur.Rchild)
    36. }
    37. }
    38. fmt.Println()
    39. }
    40. func (bt *biTree) appendNode(data interface{}) {
    41. cur := bt.root
    42. if cur == nil {
    43. bt.root = newTreeNode(data)
    44. return
    45. }
    46. Queue := []*btNode{cur}
    47. for len(Queue) > 0 {
    48. cur := Queue[0]
    49. Queue = Queue[1:]
    50. if cur.Lchild != nil {
    51. Queue = append(Queue, cur.Lchild)
    52. } else {
    53. cur.Lchild = newTreeNode(data)
    54. return
    55. }
    56. if cur.Rchild != nil {
    57. Queue = append(Queue, cur.Rchild)
    58. } else {
    59. cur.Rchild = newTreeNode(data)
    60. break
    61. }
    62. }
    63. }
    64. func main() {
    65. tree := &biTree{}
    66. list := []interface{}{1, 2, 3, 4, 5, 6}
    67. for _, data := range list {
    68. tree.appendNode(data)
    69. }
    70. levelorderPrint(tree)
    71. tree.appendNode(0)
    72. levelorderPrint(tree)
    73. }
    74. /*
    75. 1 2 3 4 5 6
    76. 1 2 3 4 5 6 0
    77. */

    二叉树的遍历

    层序遍历

    自上而下,自左至右逐层访问树的结点的过程就是层序遍历

    上面已写过打印版的层序遍历函数,稍作修改让它变成一个二叉树方法,并返回一个数组。

    1. package main
    2. import "fmt"
    3. type btNode struct {
    4. Data interface{}
    5. Lchild *btNode
    6. Rchild *btNode
    7. }
    8. type biTree struct {
    9. root *btNode
    10. }
    11. func (bt *biTree) levelorder() []interface{} {
    12. var list []interface{}
    13. cur := bt.root
    14. if cur == nil {
    15. return list
    16. }
    17. Queue := []*btNode{cur}
    18. for len(Queue) > 0 {
    19. cur := Queue[0]
    20. Queue = Queue[1:]
    21. list = append(list, cur.Data)
    22. if cur.Lchild != nil {
    23. Queue = append(Queue, cur.Lchild)
    24. }
    25. if cur.Rchild != nil {
    26. Queue = append(Queue, cur.Rchild)
    27. }
    28. }
    29. return list
    30. }
    31. func createTree(list []interface{}) *biTree {
    32. btree := &biTree{}
    33. if len(list) > 0 {
    34. btree.root = &btNode{Data: list[0]}
    35. for _, data := range list[1:] {
    36. btree.appendNode(data)
    37. }
    38. }
    39. return btree
    40. }
    41. func (bt *biTree) appendNode(data interface{}) {
    42. cur := bt.root
    43. if cur == nil {
    44. bt = &biTree{}
    45. return
    46. }
    47. Queue := []*btNode{cur}
    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 main() {
    66. list := []interface{}{1, 2, 3, 4, 5, 6}
    67. tree := createTree(list)
    68. fmt.Println(tree.levelorder())
    69. tree.appendNode(0)
    70. fmt.Println(tree.levelorder())
    71. }
    72. /*
    73. [1 2 3 4 5 6]
    74. [1 2 3 4 5 6 0]
    75. */

    先序遍历

    先遍历根节点,再遍历左节点,最后遍历右节点

    中序遍历

    先遍历左节点,再遍历根节点,最后遍历右节点

    后序遍历

    先遍历左节点,再遍历右节点,最后遍历根节点

    三种遍历的递归打印版:

    1. package main
    2. import "fmt"
    3. type btNode struct {
    4. Data interface{}
    5. Lchild *btNode
    6. Rchild *btNode
    7. }
    8. type biTree struct {
    9. root *btNode
    10. }
    11. func preorderPrint(bt *btNode) {
    12. if bt == nil {
    13. return
    14. }
    15. fmt.Print(bt.Data, " ")
    16. preorderPrint(bt.Lchild)
    17. preorderPrint(bt.Rchild)
    18. }
    19. func inorderPrint(bt *btNode) {
    20. if bt == nil {
    21. return
    22. }
    23. inorderPrint(bt.Lchild)
    24. fmt.Print(bt.Data, " ")
    25. inorderPrint(bt.Rchild)
    26. }
    27. func postorderPrint(bt *btNode) {
    28. if bt != nil { //这样写就不用return语句
    29. postorderPrint(bt.Lchild)
    30. postorderPrint(bt.Rchild)
    31. fmt.Print(bt.Data, " ")
    32. }
    33. }
    34. func createTree(list []interface{}) *biTree {
    35. btree := &biTree{}
    36. if len(list) > 0 {
    37. btree.root = &btNode{Data: list[0]}
    38. for _, data := range list[1:] {
    39. btree.appendNode(data)
    40. }
    41. }
    42. return btree
    43. }
    44. func (bt *biTree) appendNode(data interface{}) {
    45. cur := bt.root
    46. if cur == nil {
    47. bt = &biTree{}
    48. return
    49. }
    50. Queue := []*btNode{cur}
    51. for len(Queue) > 0 {
    52. cur := Queue[0]
    53. Queue = Queue[1:]
    54. if cur.Lchild != nil {
    55. Queue = append(Queue, cur.Lchild)
    56. } else {
    57. cur.Lchild = &btNode{Data: data}
    58. return
    59. }
    60. if cur.Rchild != nil {
    61. Queue = append(Queue, cur.Rchild)
    62. } else {
    63. cur.Rchild = &btNode{Data: data}
    64. break
    65. }
    66. }
    67. }
    68. func main() {
    69. list := []interface{}{1, 2, 3, 4, 5, 6, 7, 8}
    70. tree := createTree(list)
    71. preorderPrint(tree.root)
    72. fmt.Println()
    73. inorderPrint(tree.root)
    74. fmt.Println()
    75. postorderPrint(tree.root)
    76. fmt.Println()
    77. }
    78. /*
    79. 1 2 4 8 5 3 6 7
    80. 8 4 2 5 1 6 3 7
    81. 8 4 5 2 6 7 3 1
    82. */

    三个函数核心代码次序的对比:

    先序:“根左右”
                    fmt.Print(bt.Data, " ")
                    preorderPrint(bt.Lchild)
                    preorderPrint(bt.Rchild)
    中序:“左根右”
                    inorderPrint(bt.Lchild)
                    fmt.Print(bt.Data, " ")
                    inorderPrint(bt.Rchild)
    后序:“左右根”
                    postorderPrint(bt.Lchild)
                    postorderPrint(bt.Rchild)
                    fmt.Print(bt.Data, " ")

    递归非打印版:

    在打印版的基础上稍作修改,返回一个数组

    1. package main
    2. import "fmt"
    3. type btNode struct {
    4. Data interface{}
    5. Lchild *btNode
    6. Rchild *btNode
    7. }
    8. type biTree struct {
    9. root *btNode
    10. }
    11. func (bt *btNode) preorder() []interface{} {
    12. var res []interface{} //or: res := make([]interface{}, 0)
    13. if bt != nil {
    14. res = append(res, bt.Data)
    15. res = append(res, bt.Lchild.preorder()...)
    16. res = append(res, bt.Rchild.preorder()...)
    17. }
    18. return res
    19. }
    20. func (bt *btNode) inorder() []interface{} {
    21. var res []interface{}
    22. if bt != nil {
    23. res = append(res, bt.Lchild.inorder()...)
    24. res = append(res, bt.Data)
    25. res = append(res, bt.Rchild.inorder()...)
    26. }
    27. return res
    28. }
    29. func (bt *btNode) postorder() []interface{} {
    30. var res []interface{}
    31. if bt != nil {
    32. res = append(res, bt.Lchild.postorder()...)
    33. res = append(res, bt.Rchild.postorder()...)
    34. res = append(res, bt.Data)
    35. }
    36. return res
    37. }
    38. func createTree(list []interface{}) *biTree {
    39. btree := &biTree{}
    40. if len(list) > 0 {
    41. btree.root = &btNode{Data: list[0]}
    42. for _, data := range list[1:] {
    43. btree.appendNode(data)
    44. }
    45. }
    46. return btree
    47. }
    48. func (bt *biTree) appendNode(data interface{}) {
    49. cur := bt.root
    50. if cur == nil {
    51. bt = &biTree{}
    52. return
    53. }
    54. Queue := []*btNode{cur}
    55. for len(Queue) > 0 {
    56. cur := Queue[0]
    57. Queue = Queue[1:]
    58. if cur.Lchild != nil {
    59. Queue = append(Queue, cur.Lchild)
    60. } else {
    61. cur.Lchild = &btNode{Data: data}
    62. return
    63. }
    64. if cur.Rchild != nil {
    65. Queue = append(Queue, cur.Rchild)
    66. } else {
    67. cur.Rchild = &btNode{Data: data}
    68. break
    69. }
    70. }
    71. }
    72. func main() {
    73. list := []interface{}{1, 2, 3, 4, 5, 6, 7, 8}
    74. tree := createTree(list)
    75. fmt.Println(tree.root.preorder())
    76. fmt.Println(tree.root.inorder())
    77. fmt.Println(tree.root.postorder())
    78. }
    79. /*
    80. [1 2 4 8 5 3 6 7]
    81. [8 4 2 5 1 6 3 7]
    82. [8 4 5 2 6 7 3 1]
    83. */

    非递归方法:

    递推法可以写成二叉树的方法,不像递归法要反复调用只能写成结点的方法。

    1. package main
    2. import "fmt"
    3. type btNode struct {
    4. Data interface{}
    5. Lchild *btNode
    6. Rchild *btNode
    7. }
    8. type biTree struct {
    9. root *btNode
    10. }
    11. func (bt *biTree) preOrder() []interface{} {
    12. var res []interface{}
    13. p := bt.root
    14. Stack := make([]*btNode, 0)
    15. for p != nil || len(Stack) > 0 {
    16. for p != nil {
    17. res = append(res, p.Data)
    18. Stack = append(Stack, p)
    19. p = p.Lchild
    20. }
    21. if len(Stack) > 0 {
    22. p = Stack[len(Stack)-1]
    23. Stack = Stack[:len(Stack)-1]
    24. p = p.Rchild
    25. }
    26. }
    27. return res
    28. }
    29. func (bt *biTree) inOrder() []interface{} {
    30. var res []interface{}
    31. p := bt.root
    32. Stack := make([]*btNode, 0)
    33. for p != nil || len(Stack) > 0 {
    34. for p != nil {
    35. Stack = append(Stack, p)
    36. p = p.Lchild
    37. }
    38. if len(Stack) > 0 {
    39. p = Stack[len(Stack)-1]
    40. res = append(res, p.Data)
    41. Stack = Stack[:len(Stack)-1]
    42. p = p.Rchild
    43. }
    44. }
    45. return res
    46. }
    47. func (bt *biTree) postOrder() []interface{} {
    48. var res []interface{}
    49. var cur, pre *btNode
    50. Stack := make([]*btNode, 0)
    51. Stack = append(Stack, bt.root)
    52. for len(Stack) > 0 {
    53. cur = Stack[len(Stack)-1]
    54. if cur.Lchild == nil && cur.Rchild == nil ||
    55. pre != nil && (pre == cur.Lchild || pre == cur.Rchild) {
    56. res = append(res, cur.Data)
    57. Stack = Stack[:len(Stack)-1]
    58. pre = cur
    59. } else {
    60. if cur.Rchild != nil {
    61. Stack = append(Stack, cur.Rchild)
    62. }
    63. if cur.Lchild != nil {
    64. Stack = append(Stack, cur.Lchild)
    65. }
    66. }
    67. }
    68. return res
    69. }
    70. func createTree(list []interface{}) *biTree {
    71. btree := &biTree{}
    72. if len(list) > 0 {
    73. btree.root = &btNode{Data: list[0]}
    74. for _, data := range list[1:] {
    75. btree.appendNode(data)
    76. }
    77. }
    78. return btree
    79. }
    80. func (bt *biTree) appendNode(data interface{}) {
    81. cur := bt.root
    82. if cur == nil {
    83. bt = &biTree{}
    84. return
    85. }
    86. Queue := []*btNode{cur}
    87. for len(Queue) > 0 {
    88. cur := Queue[0]
    89. Queue = Queue[1:]
    90. if cur.Lchild != nil {
    91. Queue = append(Queue, cur.Lchild)
    92. } else {
    93. cur.Lchild = &btNode{Data: data}
    94. return
    95. }
    96. if cur.Rchild != nil {
    97. Queue = append(Queue, cur.Rchild)
    98. } else {
    99. cur.Rchild = &btNode{Data: data}
    100. break
    101. }
    102. }
    103. }
    104. func main() {
    105. list := []interface{}{1, 2, 3, 4, 5, 6, 7, 8}
    106. tree := createTree(list)
    107. fmt.Println(tree.preOrder())
    108. fmt.Println(tree.inOrder())
    109. fmt.Println(tree.postOrder())
    110. }
    111. /*
    112. [1 2 4 8 5 3 6 7]
    113. [8 4 2 5 1 6 3 7]
    114. [8 4 5 2 6 7 3 1]
    115. */

    更多内容请见下集分解......

  • 相关阅读:
    Vivado Synthesis - getting a Segmentation fault after using up a lot of memory.
    Docker搭建官方私有仓库registry及相关配置
    装饰模式 rust和java的实现
    回到街头 - 数字时尚嘉年华:Web3的时尚未来,4月香港兰桂坊盛大启幕
    NLP实践!文本语法纠错模型实战,搭建你的贴身语法修改小助手 ⛵
    【Python工程师之高性能爬虫】
    [最短路]猛犸不上 Ban 2021RoboCom决赛D
    C++ Reference: Standard C++ Library reference: C Library: cmath: remquo
    JSP项目进度管理系统myeclipse开发sql数据库BS模式java编程网页结构
    WPF 分组
  • 原文地址:https://blog.csdn.net/boysoft2002/article/details/126556510