当前位置:   article > 正文

二叉树;二叉树的前序、中序、后序遍历及查找;顺序存储二叉树;线索化二叉树_先序查找二叉树

先序查找二叉树

数组、链表和树存储方式分析

对于树结构,不论是查找修改还是增加删除,效率都比较高,结合了链表和数组的优点,如以下的二叉树:

1、数组的第一个元素作为第一个节点

2、数组的第二个元素3比7小,放在7的左边

3、数组的第三个元素10比7大,放在7的右边

4、数组的第四个元素1比7小,也比3小,放在3的左边

5、数组的第五个元素5比7小,但比3大,放在3的右边

6、数组的第六个元素9比7大,但比10小,放在10的左边

7、数组的第七个元素12比7大,比10大,放在10的右边

二叉树的前中后序遍历

思路分析

代码实现

  1. # 创建 HeroNode 节点
  2. class HeroNode:
  3. def __init__(self, no: int, name: str):
  4. self.no = no
  5. self.name = name
  6. self.left = None
  7. self.right = None
  8. def __str__(self):
  9. return f"no={self.no}, name={self.name}"
  10. # 前序遍历
  11. def pre_order(self):
  12. # 先输出父节点
  13. print(self, end=' => ')
  14. # 左子树不为空则递归左子树
  15. if self.left is not None:
  16. self.left.pre_order()
  17. # 右子树不为空则递归右子树
  18. if self.right is not None:
  19. self.right.pre_order()
  20. # 中序遍历
  21. def infix_order(self):
  22. # 左子树不为空则递归左子树
  23. if self.left is not None:
  24. self.left.infix_order()
  25. # 输出父节点
  26. print(self, end=' => ')
  27. # 右子树不为空则递归右子树
  28. if self.right is not None:
  29. self.right.infix_order()
  30. # 后序遍历
  31. def post_order(self):
  32. # 左子树不为空则递归左子树
  33. if self.left is not None:
  34. self.left.post_order()
  35. # 右子树不为空则递归右子树
  36. if self.right is not None:
  37. self.right.post_order()
  38. # 输出父节点
  39. print(self, end=' => ')
  40. # 建立 HeroNode 二叉树
  41. class BinaryTree:
  42. root: HeroNode = None
  43. # 前序遍历
  44. def pre_order(self):
  45. if self.root is not None:
  46. self.root.pre_order()
  47. else:
  48. print("二叉树为空...")
  49. # 前序遍历
  50. def infix_order(self):
  51. if self.root is not None:
  52. self.root.infix_order()
  53. else:
  54. print("二叉树为空...")
  55. # 前序遍历
  56. def post_order(self):
  57. if self.root is not None:
  58. self.root.post_order()
  59. else:
  60. print("二叉树为空...")
  61. def test_binary_tree():
  62. # 手动创建二叉树
  63. binary_tree = BinaryTree()
  64. root = HeroNode(1, '宋江')
  65. node2 = HeroNode(2, '吴用')
  66. node3 = HeroNode(3, '卢俊义')
  67. node4 = HeroNode(4, '林冲')
  68. root.left = node2
  69. root.right = node3
  70. node3.right = node4
  71. binary_tree.root = root
  72. # 前序
  73. print("前序遍历:", end=" ")
  74. binary_tree.pre_order()
  75. print()
  76. # 中序
  77. print("中序遍历:", end=" ")
  78. binary_tree.infix_order()
  79. print()
  80. # 后序
  81. print("后序遍历:", end=" ")
  82. binary_tree.post_order()
  83. print()
  84. test_binary_tree()

二叉树的前中后序查找

思路分析

代码实现

  1. """ 前中后序遍历查找 """
  2. # 创建 HeroNode 节点
  3. class HeroNode:
  4. def __init__(self, no: int, name: str):
  5. self.no = no
  6. self.name = name
  7. self.left = None
  8. self.right = None
  9. def __str__(self):
  10. return f"no={self.no}, name={self.name}"
  11. # 前序遍历查找
  12. def pre_order_search(self, no: int):
  13. """
  14. 前序遍历查找某个节点
  15. :param no: 要查找节点的 id
  16. :return: 找到的 HeroNode 节点或 None
  17. """
  18. print("进入前序遍历...")
  19. if self.no == no: # 如果当前节点是,直接返回
  20. return self
  21. find_node = None
  22. # 如果左子节点不为空,则向左子节点继续递归查找
  23. # 找到则返回,找不到则看右子节点
  24. if self.left is not None:
  25. find_node = self.left.pre_order_search(no)
  26. if find_node: # 说明在左子树上找到,直接返回
  27. return find_node
  28. # 否则判断右子节点,若不为空,向右子树递归查找
  29. if self.right is not None:
  30. find_node = self.right.pre_order_search(no)
  31. # 如果右子树找到,则find_node有值,否则find_node为空
  32. return find_node
  33. # 中序遍历查找
  34. def infix_order_search(self, no: int):
  35. """
  36. 中序遍历查找某个节点
  37. :param no: 要查找节点的 id
  38. :return: 找到的 HeroNode 节点或 None
  39. """
  40. find_node = None
  41. # 如果左子节点不为空,则向左子节点继续递归查找
  42. # 找到则返回,找不到则看右子节点
  43. if self.left is not None:
  44. find_node = self.left.infix_order_search(no)
  45. if find_node: # 说明在左子树上找到,直接返回
  46. return find_node
  47. print("进入中序遍历...")
  48. if self.no == no: # 如果当前节点是,直接返回
  49. return self
  50. # 否则判断右子节点,若不为空,向右子树递归查找
  51. if self.right is not None:
  52. find_node = self.right.infix_order_search(no)
  53. # 如果右子树找到,则find_node有值,否则find_node为空
  54. return find_node
  55. # 后序遍历查找
  56. def post_order_search(self, no: int):
  57. """
  58. 后序遍历查找某个节点
  59. :param no: 要查找节点的 id
  60. :return: 找到的 HeroNode 节点或 None
  61. """
  62. find_node = None
  63. # 如果左子节点不为空,则向左子节点继续递归查找
  64. # 找到则返回,找不到则看右子节点
  65. if self.left is not None:
  66. find_node = self.left.post_order_search(no)
  67. if find_node: # 说明在左子树上找到,直接返回
  68. return find_node
  69. # 否则判断右子节点,若不为空,向右子树递归查找
  70. if self.right is not None:
  71. find_node = self.right.post_order_search(no)
  72. # 如果右子树找到,则find_node有值,否则find_node为空
  73. if find_node:
  74. return find_node
  75. print("进入后序遍历...")
  76. if self.no == no: # 如果当前节点是,直接返回
  77. return self
  78. return None
  79. # 建立 HeroNode 二叉树
  80. class BinaryTree:
  81. root: HeroNode = None
  82. # 前序查找
  83. def pre_order_search(self, no):
  84. if self.root is not None:
  85. return self.root.pre_order_search(no)
  86. else:
  87. return None
  88. # 中序查找
  89. def infix_order_search(self, no):
  90. if self.root is not None:
  91. return self.root.infix_order_search(no)
  92. else:
  93. return None
  94. # 后序查找
  95. def post_order_search(self, no):
  96. if self.root is not None:
  97. return self.root.post_order_search(no)
  98. else:
  99. return None
  100. def test_binary_tree():
  101. # 手动创建二叉树
  102. binary_tree = BinaryTree()
  103. root = HeroNode(1, '宋江')
  104. node2 = HeroNode(2, '吴用')
  105. node3 = HeroNode(3, '卢俊义')
  106. node4 = HeroNode(4, '林冲')
  107. node5 = HeroNode(5, "关胜")
  108. root.left = node2
  109. root.right = node3
  110. node3.right = node4
  111. node3.left = node5
  112. binary_tree.root = root
  113. print("前序遍历查找:") # 比较了4次(看输出得到的结果)
  114. res = binary_tree.pre_order_search(5)
  115. if res:
  116. print("找到了,节点信息为:", res)
  117. else:
  118. print("找不到编号为5的节点")
  119. print()
  120. print("中序遍历查找:") # 比较了3次(看输出得到的结果)
  121. res = binary_tree.infix_order_search(5)
  122. if res:
  123. print("找到了,节点信息为:", res)
  124. else:
  125. print("找不到编号为5的节点")
  126. print()
  127. print("后序遍历查找:") # 比较了2次(看输出得到的结果)
  128. res = binary_tree.post_order_search(5)
  129. if res:
  130. print("找到了,节点信息为:", res)
  131. else:
  132. print("找不到编号为5的节点")
  133. test_binary_tree()

二叉树删除节点

思路分析

代码实现

  1. """ 递归删除二叉树节点 """
  2. # HeroNode 节点
  3. class HeroNode:
  4. def __init__(self, no: int, name: str):
  5. self.no = no
  6. self.name = name
  7. self.left = None
  8. self.right = None
  9. def __str__(self):
  10. return f"no={self.no}, name={self.name}"
  11. # 前序遍历
  12. def pre_order(self):
  13. # 先输出父节点
  14. print(self, end=' => ')
  15. # 左子树不为空则递归左子树
  16. if self.left is not None:
  17. self.left.pre_order()
  18. # 右子树不为空则递归右子树
  19. if self.right is not None:
  20. self.right.pre_order()
  21. def delete_node(self, no: int):
  22. """
  23. 递归删除节点规则:
  24. 如果删除的节点是叶子节点,则直接删除
  25. 如果删除的节点不是叶子节点,则删除该节点及其左右子树
  26. :param no: 要删除的节点编号
  27. :return:
  28. """
  29. # 如果左子节点不为空,且左子节点是要删除的节点,则删除左子节点及其子树,并返回
  30. if self.left and self.left.no == no:
  31. self.left = None # 相当于删除左子节点及其子树
  32. return
  33. # 如果右子节点不为空,且右子节点是要删除的节点,则删除右子节点及其子树,并返回
  34. if self.right and self.right.no == no:
  35. self.right = None # 相当于删除右子节点及其子树
  36. return
  37. # 如果左右子节点都不是要删除的节点,则首先向左子节点递归删除
  38. if self.left:
  39. self.left.delete_node(no)
  40. # 如果递归完左子节点还没找到要删除的节点,则继续向右子节点递归删除
  41. if self.right:
  42. self.right.delete_node(no)
  43. # 建立 HeroNode 二叉树
  44. class BinaryTree:
  45. root: HeroNode = None
  46. # 前序遍历
  47. def pre_order(self):
  48. if self.root is not None:
  49. self.root.pre_order()
  50. else:
  51. print("二叉树为空...")
  52. # 删除树节点
  53. def delete_node(self, no: int):
  54. if self.root:
  55. if self.root.no == no: # 如果根节点是要删除的节点
  56. self.root = None # 则把根节点置空
  57. else:
  58. self.root.delete_node(no)
  59. else:
  60. print("树空,不能删除节点...")
  61. def test_binary_tree():
  62. # 手动创建二叉树
  63. binary_tree = BinaryTree()
  64. root = HeroNode(1, '宋江')
  65. node2 = HeroNode(2, '吴用')
  66. node3 = HeroNode(3, '卢俊义')
  67. node4 = HeroNode(4, '林冲')
  68. node5 = HeroNode(5, "关胜")
  69. root.left = node2
  70. root.right = node3
  71. node3.right = node4
  72. node3.left = node5
  73. binary_tree.root = root
  74. print("删除前:", end='')
  75. binary_tree.pre_order()
  76. print()
  77. binary_tree.delete_node(5)
  78. print("删除后:", end='')
  79. binary_tree.pre_order()
  80. print()
  81. test_binary_tree()

顺序存储二叉树

思路分析

代码实现

需求如下:

  1. """顺序存储二叉树"""
  2. # 顺序存储二叉树就是用数组结构存储二叉树节点数据,
  3. # 要求用数组存储后,可以对该数组进行前序遍历、中序遍历、后序遍历
  4. # 其实就是将二叉树从左到右,从上到下的节点依次存入数组中,如下:
  5. """
  6. 假设有如下一棵二叉树,它对应的顺序存储就是:arr = [1, 2, 3, 4, 5, 6, 7]
  7. 1
  8. 2 3
  9. 4 5 6 7
  10. """
  11. class ArrayBinaryTree:
  12. def __init__(self, arr):
  13. self.arr = arr
  14. def pre_order(self, index: int):
  15. """
  16. 以前序遍历方式访问数组元素
  17. :param index: 数组下标
  18. :return:
  19. """
  20. n = len(self.arr) # n为数组长度
  21. if self.arr and n > 0:
  22. # 输出当前元素
  23. print(f"arr[{index}]={self.arr[index]}", end=" ")
  24. # 向左子树递归
  25. if 2 * index + 1 < n:
  26. self.pre_order(2 * index + 1)
  27. # 向右子树递归
  28. if 2 * index + 2 < n:
  29. self.pre_order(2 * index + 2)
  30. else:
  31. print("数组为空!")
  32. def infix_order(self, index: int):
  33. """
  34. 以中序遍历方式访问数组元素
  35. :param index: 数组下标
  36. :return:
  37. """
  38. n = len(self.arr)
  39. if self.arr and n > 0:
  40. if 2 * index + 1 < n: # 向左子树递归
  41. self.infix_order(2 * index + 1)
  42. print(f"arr[{index}]={self.arr[index]}", end=" ")
  43. if 2 * index + 2 < n: # 向右子树递归
  44. self.infix_order(2 * index + 2)
  45. else:
  46. print("数组为空")
  47. def post_order(self, index: int):
  48. """
  49. 以后序遍历方式访问数组元素
  50. :param index: 数组下标
  51. :return:
  52. """
  53. n = len(self.arr)
  54. if self.arr and n > 0:
  55. if 2 * index + 1 < n: # 向左子树递归
  56. self.post_order(2 * index + 1)
  57. if 2 * index + 2 < n: # 向右子树递归
  58. self.post_order(2 * index + 2)
  59. print(f"arr[{index}]={self.arr[index]}", end=" ")
  60. arr_binary_tree = ArrayBinaryTree([1, 2, 3, 4, 5, 6, 7])
  61. print("前序遍历:")
  62. arr_binary_tree.pre_order(0)
  63. print()
  64. print("中序遍历:")
  65. arr_binary_tree.infix_order(0)
  66. print()
  67. print("后序遍历:")
  68. arr_binary_tree.post_order(0)
  69. print()

线索化二叉树

简单介绍

思路分析

遍历线索化二叉树

线索化二叉树和遍历线索化二叉树的代码实现

  1. """ 线索化二叉树 """
  2. # 创建 Node 节点
  3. class Node:
  4. no: int = None
  5. left = None
  6. right = None
  7. # left_type/right_type 表示指针类型
  8. # 值为0时表示指向的是左子树/右子树,为1时表示指向的是前驱节点/后继节点
  9. left_type: int = 0
  10. right_type: int = 0
  11. def __init__(self, no: int):
  12. self.no = no
  13. self.left = None
  14. self.right = None
  15. def __str__(self):
  16. return f"no={self.no}"
  17. # 建立线索化 Node 二叉树
  18. class ThreadedBinaryTree:
  19. root: Node = None
  20. # 为了实现线索化,需要一个指针(变量)指向当前节点的前驱节点
  21. # 如中序线索化中,需要一个指针(变量)指向当前节点在中序遍历结果中的前驱节点
  22. # 在递归进行线索化时, pre 总指向当前节点按某种遍历方式结果的前驱节点
  23. pre: Node = None
  24. # 建立中序线索化二叉树
  25. def threaded_infix_tree(self, node: Node):
  26. """
  27. 建立中序线索化二叉树
  28. :param node: 要线索化的节点
  29. :return:
  30. """
  31. if node is None: # 节点为空,不需要线索化
  32. return
  33. # 先线索化左子树
  34. self.threaded_infix_tree(node.left)
  35. # 线索化当前节点
  36. # 结合图形理解代码,第一个要线索化的节点是8
  37. # 先处理当前节点的左子节点
  38. if node.left is None: # 如果当前节点的左指针为空,则让左指针指向当前节点的前驱节点pre
  39. node.left = self.pre
  40. node.left_type = 1 # 设置指针类型为1,表示该指针指向的是前驱节点
  41. # 处理后继节点
  42. if self.pre and self.pre.right is None:
  43. self.pre.right = node
  44. self.pre.right_type = 1 # 设置指针类型为1,表示该指针指向的是后继节点
  45. # 每处理一个节点后,让当前节点成为下一个节点的前驱节点
  46. self.pre = node
  47. # 后线索化右子树
  48. self.threaded_infix_tree(node.right)
  49. # 遍历中序线索化二叉树
  50. def for_in_tree(self):
  51. node = self.root
  52. while node:
  53. # 循环找到 left_type = 1 的节点,该节点就是中序遍历的第一个节点,即图中的节点8
  54. while node.left_type == 0:
  55. node = node.left
  56. # 输出当前节点
  57. print(node, end=" ")
  58. # 如果当前节点的右指针指向的是后继节点,则一直输出
  59. while node.right_type == 1:
  60. node = node.right
  61. print(node, end=" ")
  62. # 替换要遍历的节点,具体过程通过debug和结合图来看会更容易理解
  63. node = node.right
  64. def test_binary_tree():
  65. # 手动创建二叉树
  66. binary_tree = BinaryTree()
  67. root = Node(1)
  68. node2 = Node(3)
  69. node3 = Node(6)
  70. node4 = Node(8)
  71. node5 = Node(10)
  72. node6 = Node(14)
  73. root.left = node2
  74. root.right = node3
  75. node2.left = node4
  76. node2.right = node5
  77. node3.left = node6
  78. threaded_binary_tree = ThreadedBinaryTree()
  79. threaded_binary_tree.root = root
  80. # 测试线索化
  81. print(f"线索化前:10的left={node5.left},right={node5.right}")
  82. threaded_binary_tree.threaded_infix_tree(root)
  83. # 以10号节点,即node5测试
  84. print(f"线索化后:10的前驱节点={node5.left},后继节点={node5.right}")
  85. # 测试遍历线索化二叉树
  86. threaded_binary_tree.for_in_tree()
  87. test_binary_tree()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/275023
推荐阅读
相关标签
  

闽ICP备14008679号