当前位置:   article > 正文

js递归遍历树结构_二分搜索树(BST)的前/中/后序遍历-递归+非递归

jsbst

二分搜索树(BST)

树结构是一种常见的组织结构,树结构效率出奇的高。

ecbf50781a1c69bef053bcf95de0d49d.png

认识二叉树

二叉树是和链表一样,都是动态数据结构。

二叉树具有唯一的根节点,每个节点最多有一个父节点,最多有两个孩子节点。

dccf56dd9f8c6b0bbc1c2f4864fca2aa.png

二叉树具有天然的递归结构:每个节点的左/右子树也是一棵二叉树。

1884ce84e8fbc604307d07a6e127ad97.png

二叉树不一定是满的,一个节点也是二叉树,空树也是二叉树。

e1df6b93d0594fccc804386471b5f352.png

二分搜索树(Binary Search Tree)

二分搜索树中存储的元素必须就有可比较性。

58cb71c11e391b7973848c5f1bb71119.png

中序遍历(In-Order Traverse)二分搜索树得到的是一个升序序列。

向二分搜索树中插入节点

插入新节点时,先寻找到合适的位置,不能破坏二分搜索树的性质,然后执行插入操作。

af6f9794fd307e2fbb5a601cca986d7d.png

de73330d1c9c69d67a0e0d35b226e98d.png

二分搜索树的遍历

二分搜索树的遍历需要掌握: 先序、中序、后序遍历的递归和非递归实现以及层序遍历。

先/中/后序遍历的递归实现

先序遍历的顺序是:根->左->右。 中序遍历的顺序是:左->根->右。 后序遍历的顺序是:左->右->根

16d02014b16856a031fc0d67ed9955f9.png

先序遍历的非递归实现

通过使用一个栈来实现先序遍历非递归算法。

d3324e779ddca84f0a2932c7cb4db425.png

7dbaa8f9ac6c846590981025302d4763.png

中序遍历的非递归实现

中序遍历非递归算法同样需要使用一个栈来实现。

bd8465f2a09e6187ed7547e6d5f20567.png

0fce84df4d7a9bd991cd8a49c9c0a258.png

d6c61836cb68225009600577a1f522c4.png

后序遍历的非递归实现

后序遍历的顺序为:左->右->根。根节点最后访问,也就是说,只有当为空或者已经被访问,根节点才可以被访问。

ff68aa1cba163c041fbd6d2516fd0b38.png

d17e35e85c4f9b8194c323f68d340af4.png

d53412c9eb37e204c4b38a20902a8932.png

bc19a3475e22df69b7a14eaa52ec35a6.png

二分搜索树的层序遍历

5ba300e3addcb3c419fb83e0fb3830ac.png

二叉树的层序遍历需要使用队列辅助。

9ae430cae77e817449c17bd1e22b85d7.png

773d3ef662d035386bad45717ea44e34.png

二分搜索树的实现

  1. #ifndef BST_H
  2. #define BST_H
  3. #include <iostream>
  4. #include <stack>
  5. #include <queue>
  6. using namespace std;
  7. template <typename T>
  8. class bst
  9. {
  10. private:
  11. struct node
  12. {
  13. T e;
  14. node* left;
  15. node* right;
  16. node() : e(), left(nullptr), right(nullptr) {}
  17. node(T e) : e(e), left(nullptr), right(nullptr) {}
  18. node(T e, node* left, node* right) : e(e), left(left), right(right) {}
  19. };
  20. public:
  21. bst()
  22. {
  23. root_ = nullptr;
  24. size_ = 0;
  25. }
  26. ~bst()
  27. {
  28. destroy_tree(root_);
  29. }
  30. void add(T e)
  31. {
  32. root_ = add(root_, e);
  33. }
  34. int get_size()
  35. {
  36. return size_;
  37. }
  38. void pre_order_traverse()
  39. {
  40. pre_order_traverse(root_);
  41. cout << endl;
  42. }
  43. void in_order_traverse()
  44. {
  45. in_order_traverse(root_);
  46. cout << endl;
  47. }
  48. void post_order_traverse()
  49. {
  50. post_order_traverse(root_);
  51. cout << endl;
  52. }
  53. // previous order traverse no recursion
  54. void pre_order_traverse_nr()
  55. {
  56. pre_order_traverse_nr(root_);
  57. }
  58. void in_order_traverse_nr()
  59. {
  60. in_order_traverse_nr(root_);
  61. }
  62. void post_order_traverse_nr()
  63. {
  64. post_order_traverse_nr(root_);
  65. }
  66. void level_order_traverse()
  67. {
  68. level_order_traverse(root_);
  69. }
  70. private:
  71. node* root_;
  72. int size_;
  73. void destroy_tree(node* root)
  74. {
  75. if (root == nullptr)
  76. return;
  77. destroy_tree(root->left);
  78. destroy_tree(root->right);
  79. cout <<delete: “ << root->e << endl;
  80. delete root;
  81. root = nullptr;
  82. }
  83. node* add(node* root, T e);
  84. void pre_order_traverse(node* root);
  85. void in_order_traverse(node* root);
  86. void post_order_traverse(node* root);
  87. // 非递归算法
  88. void pre_order_traverse_nr(node* root);
  89. void in_order_traverse_nr(node* root);
  90. void post_order_traverse_nr(node* root);
  91. void level_order_traverse(node* root);
  92. };
  93. template <typename T>
  94. typename bst<T>::node* bst<T>::add(node* root, T e)
  95. {
  96. if (root == nullptr)
  97. {
  98. size_++;
  99. return new node(e);
  100. }
  101. if (root->e > e)
  102. root->left = add(root->left, e);
  103. else if (root->e < e)
  104. root->right = add(root->right, e);
  105. else
  106. root->e = e; // do nothing
  107. return root;
  108. }
  109. template <typename T>
  110. void bst<T>::pre_order_traverse(node* root)
  111. {
  112. if (root == nullptr)
  113. return;
  114. cout << root->e << “ “;
  115. pre_order_traverse(root->left);
  116. pre_order_traverse(root->right);
  117. }
  118. template <typename T>
  119. void bst<T>::in_order_traverse(node* root)
  120. {
  121. if (root == nullptr)
  122. return;
  123. in_order_traverse(root->left);
  124. cout << root->e << “ “;
  125. in_order_traverse(root->right);
  126. }
  127. template <typename T>
  128. void bst<T>::post_order_traverse(node* root)
  129. {
  130. if (root == nullptr)
  131. return;
  132. post_order_traverse(root->left);
  133. post_order_traverse(root->right);
  134. cout << root->e << " ";
  135. }
  136. template <typename T>
  137. void bst<T>::pre_order_traverse_nr(node* root)
  138. {
  139. if (root == nullptr)
  140. return;
  141. stack<node*> st;
  142. st.push(root);
  143. while (!st.empty())
  144. {
  145. node* curr = st.top();
  146. cout << curr->e << “ “;
  147. st.pop();
  148. if (curr->right != nullptr)
  149. st.push(curr->right);
  150. if (curr->left != nullptr)
  151. st.push(curr->left);
  152. }
  153. cout << endl;
  154. }
  155. template <typename T>
  156. void bst<T>::in_order_traverse_nr(node* root)
  157. {
  158. stack<node*> st;
  159. node* curr = root;
  160. while (curr != nullptr || !st.empty())
  161. {
  162. while (curr != nullptr)
  163. {
  164. st.push(curr);
  165. curr = curr->left;
  166. }
  167. if (!st.empty())
  168. {
  169. curr = st.top();
  170. cout << curr->e << “ “;
  171. st.pop();
  172. curr = curr->right;
  173. }
  174. }
  175. cout << endl;
  176. }
  177. template <typename T>
  178. void bst<T>::post_order_traverse_nr(node* root)
  179. {
  180. stack<node*> st;
  181. node* curr = root;
  182. node* visited = nullptr;
  183. while (curr != nullptr || !st.empty())
  184. {
  185. while (curr != nullptr)
  186. {
  187. st.push(curr);
  188. curr = curr->left;
  189. }
  190. if (!st.empty())
  191. {
  192. curr = st.top();
  193. if (curr->right == visited || curr->right == nullptr)
  194. {
  195. cout << curr->e << “ “;
  196. st.pop();
  197. visited = curr;
  198. curr = nullptr;
  199. }
  200. else
  201. curr = curr->right;
  202. }
  203. }
  204. cout << endl;
  205. }
  206. template <typename T>
  207. void bst<T>::level_order_traverse(node* root)
  208. {
  209. if (root == nullptr)
  210. return;
  211. queue<node*> q;
  212. q.push(root);
  213. while (!q.empty())
  214. {
  215. node* curr = q.front();
  216. q.pop();
  217. if (curr->left != nullptr)
  218. q.push(curr->left);
  219. if (curr->right != nullptr)
  220. q.push(curr->right);
  221. cout << curr->e << “ “;
  222. }
  223. cout << endl;
  224. }
  225. #endif // BST_H

测试程序

  1. #include “bst.h”
  2. #include <cstdlib>
  3. int main()
  4. {
  5. bst<int>* my_bst = new bst<int>();
  6. srand(time(nullptr));
  7. my_bst->add(54);
  8. my_bst->add(32);
  9. my_bst->add(77);
  10. my_bst->add(18);
  11. my_bst->add(45);
  12. my_bst->add(66);
  13. my_bst->add(81);
  14. cout << “Pre-Order Traverse: “ << endl;
  15. my_bst->pre_order_traverse();
  16. my_bst->pre_order_traverse_nr();
  17. cout << endl;
  18. cout << “In-Order Traverse: “ << endl;
  19. my_bst->in_order_traverse();
  20. my_bst->in_order_traverse_nr();
  21. cout << endl;
  22. cout << “Post-Order Traverse: “ << endl;
  23. my_bst->post_order_traverse();
  24. my_bst->post_order_traverse_nr();
  25. cout << endl;
  26. cout << “Lever Order Traverse: “ << endl;
  27. my_bst->level_order_traverse();
  28. delete my_bst;
  29. return 0;
  30. }

测试结果。通过观察法可以看出,二叉树的遍历结果是正确的。

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

闽ICP备14008679号