当前位置:   article > 正文

【数据结构】--- 二叉树的递归遍历和非递归遍历【C语言实现】_c语言二叉树的非递归遍历

c语言二叉树的非递归遍历

目录

1. 创建一颗二叉树

2.递归前序遍历二叉树

3.递归中序遍历二叉树

4.递归后序遍历二叉树

5. 测试递归打印二叉树代码

6. 非-递归前序遍历二叉树

7. 非-递归实现中序遍历二叉树

8. 非 - 递归实现后序遍历【较为复杂的方法】

9. 非 - 递归实现后序遍历【简单的方法】

10. 二叉树的层次遍历

11. 最后:附全部代码:


对于二叉树的非递归 深度优先遍历,使用的都是栈

对于二叉树的层次遍历,使用的是队列

1. 创建一颗二叉树

依据前序遍历创建二叉树:,树结构如上图所示

输入:  ABD##E##C##

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. // 二叉树的实现
  4. // 定义 二叉树的 结构体
  5. typedef struct node{
  6. char data;
  7. struct node *left;
  8. struct node *right;
  9. }Node, *Tree;
  10. // 依据前序遍历创建二叉树
  11. // 根左右: ABD##E##C##
  12. Tree create_tree(){
  13. Node *root = NULL;
  14. char ch;
  15. scanf("%c", &ch); // 输入 ABD##E##C##
  16. if (ch != '#'){
  17. root = (Node*)malloc(sizeof(Node));
  18. root->data = ch;
  19. root->left = create_tree(); // 递归创建
  20. root->right = create_tree();
  21. }
  22. else{
  23. root = NULL;
  24. }
  25. return root;
  26. }

2.递归前序遍历二叉树

  1. // 递归前序遍历二叉树
  2. void preOrderRec(Tree root){
  3. if (root != NULL){
  4. printf(" %c - ", root->data);
  5. preOrderRec(root->left);
  6. preOrderRec(root->right);
  7. }
  8. }

3.递归中序遍历二叉树

  1. // 递归中序遍历二叉树
  2. void inOrderRec(Tree root){
  3. if (root != NULL){
  4. inOrderRec(root->left);
  5. printf(" %c - ", root->data);
  6. inOrderRec(root->right);
  7. }
  8. }

4.递归后序遍历二叉树

  1. void backOrderRec(Tree root){
  2. if (root != NULL){
  3. backOrderRec(root->left);
  4. backOrderRec(root->right);
  5. printf(" %c - ", root->data);
  6. }
  7. }

5. 测试递归打印二叉树代码

  1. int main(){
  2. printf("starting ------ \n");
  3. Tree root = create_tree();
  4. printf("递归前序遍历--- \n");
  5. preOrderRec(root);
  6. printf("\n");
  7. printf("递归中序遍历--- \n");
  8. inOrderRec(root);
  9. printf("\n");
  10. printf("递归后序遍历--- \n");
  11. backOrderRec(root);
  12. printf("\n");
  13. return 0;
  14. }

6. 非-递归前序遍历二叉树

前序遍历顺序是:根-左-右

先打印根节点的值,由于栈是先进后出,所以先将 右子树放进去,再将左子树放进去

  1. // 非-递归前序遍历二叉树
  2. void preOrderNRec(Tree root){
  3. Tree stack[MAXSIZE], node;
  4. int k = -1;
  5. if (root == NULL){
  6. printf("tree is empty-- \n");
  7. return;
  8. }
  9. else{
  10. k++;
  11. // 仿照一个栈
  12. stack[k] = root; // 将根节点入栈
  13. while (k > -1){
  14. //出栈
  15. node = stack[k--];
  16. printf(" %c - ", node->data);
  17. // 先把右子树放进去,栈是先进去后出,所以下面的左子树先出
  18. if (node->right != NULL){
  19. stack[++k] = node->right;
  20. }
  21. if (node->left != NULL){
  22. stack[++k] = node->left;
  23. }
  24. }
  25. }
  26. }

7. 非-递归实现中序遍历二叉树

中序遍历的非递归方式实现思想是:

1. 从根结点开始,遍历左孩子同时压栈,当遍历结束,说明当前遍历的结点没有左孩子,

2. 从栈中取出来调用操作函数,然后访问该结点的右孩子,继续以上重复性的操作。

  1. // 非-递归实现中序遍历二叉树
  2. void inOrderNRec(Tree root){
  3. Tree stack[MAXSIZE], node;
  4. int top = 0;
  5. // 判断树是否为空
  6. if (root == NULL){
  7. printf("tree is empty-- \n");
  8. return;
  9. }
  10. node = root;
  11. while (node != NULL || top > 0){
  12. // 将所有的左子树节点入栈
  13. while (node != NULL){
  14. stack[++top] = node;
  15. node = node->left;
  16. }
  17. // 如果右节点为空的话,执行下列语句
  18. node = stack[top--];
  19. printf(" %c - ", node->data);
  20. // 扫描右节点
  21. node = node->right;
  22. }
  23. }

8. 非 - 递归实现后序遍历【较为复杂的方法】

  1. void backOrderNRec(Tree root){
  2. Node *p = root;
  3. Node *stack[MAXSIZE];
  4. int num = 0;
  5. Node *have_visited = NULL;
  6. while (NULL != p || num>0)
  7. {
  8. while (NULL != p)
  9. {
  10. stack[num++] = p;
  11. p = p->left;
  12. }
  13. p = stack[num - 1];
  14. if (NULL == p->right || have_visited == p->right)
  15. {
  16. printf(" %c - ", p->data);
  17. num--;
  18. have_visited = p;
  19. p = NULL;
  20. }
  21. else
  22. {
  23. p = p->right;
  24. }
  25. }
  26. }

9. 非 - 递归实现后序遍历【简单的方法】

非递归实现后序遍历还是很复杂的,变来变去,指来指去的

但是,我发现一种简单的方法

我们知道 后序遍历的顺序为: 

后序:左->右->根

那么可以把后序当作:根->右->左,最后再反转回来即可。

由于我们是使用的栈,所以先保存根节点, 然后先放进去 左节点,再放 进去 右节点

  1. void backOrderNRecSimple(Tree root){
  2. Tree stack[MAXSIZE], node;
  3. int top = 0;
  4. int count = 0;
  5. char array[MAXSIZE]; // 使用一个数组来保存数据,方便最后数组的反转
  6. if (root == NULL){
  7. printf("tree is empty-- \n");
  8. return;
  9. }
  10. else{
  11. top++;
  12. // 仿照一个栈
  13. stack[top] = root; // 将根节点入栈
  14. while (top > 0){
  15. //出栈
  16. node = stack[top--];
  17. array[count++] = node->data; // 将其保存在一个数组当中
  18. // 先把右子树放进去,栈是先进去后出,所以下面的左子树先出
  19. if (node->left != NULL){
  20. stack[++top] = node->left; // 入栈
  21. }
  22. if (node->right != NULL){
  23. stack[++top] = node->right;
  24. }
  25. }
  26. }
  27. // 反转数组,输出
  28. for (int i = count-1; i >= 0; i--){
  29. printf(" %c - ", array[i]);
  30. }
  31. }

附上java代码,更为简单:

  1. ArrayList<Integer> postOrder(TreeNode root) {
  2. ArrayList<Integer> list = new ArrayList<Integer>();
  3. if (root != null) {
  4. Stack<TreeNode> stack = new Stack<TreeNode>();
  5. stack.push(root);
  6. while (!stack.isEmpty()) {
  7. TreeNode node = stack.pop();
  8. list.add(node.val);
  9. if (node.left != null) {
  10. stack.push(node.left);
  11. }
  12. if (node.right != null) {
  13. stack.push(node.right);
  14. }
  15. }
  16. //反转
  17. Collections.reverse(list);
  18. }
  19. return list;
  20. }

10. 二叉树的层次遍历

层次遍历使用的是  队列来实现

  1. void Level_traversal(Tree root){
  2. if (root == NULL){
  3. printf("tree is empty-- \n");
  4. return;
  5. }
  6. Tree stack[MAXSIZE], node;
  7. node = root;
  8. int front = 0; // 使用 front, rear模拟队列
  9. int rear = 0;
  10. stack[rear++] = node;
  11. while (front != rear){
  12. node = stack[front++]; // 模拟队列,先获取front当前元素,然后在指向 front ++ 位元素
  13. printf(" %c - ", node->data);
  14. // 左右子树入队列
  15. if (node->left != NULL){
  16. stack[rear++] = node->left;
  17. }
  18. if (node->right != NULL){
  19. stack[rear++] = node->right;
  20. }
  21. }
  22. }

11. 最后:附全部代码:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define MAXSIZE 100
  4. // 二叉树的实现
  5. // 定义 二叉树的 结构体
  6. typedef struct node{
  7. char data;
  8. struct node *left;
  9. struct node *right;
  10. }Node, *Tree;
  11. // 依据前序遍历创建二叉树
  12. // 根左右: ABD##E##C##
  13. Tree create_tree(){
  14. Node *root = NULL;
  15. char ch;
  16. scanf("%c", &ch); // 输入 ABD##E##C##
  17. if (ch != '#'){
  18. root = (Node*)malloc(sizeof(Node));
  19. root->data = ch;
  20. root->left = create_tree(); // 递归创建
  21. root->right = create_tree();
  22. }
  23. else{
  24. root = NULL;
  25. }
  26. return root;
  27. }
  28. // 递归前序遍历二叉树
  29. void preOrderRec(Tree root){
  30. if (root != NULL){
  31. printf(" %c - ", root->data);
  32. preOrderRec(root->left);
  33. preOrderRec(root->right);
  34. }
  35. }
  36. // 非-递归前序遍历二叉树
  37. void preOrderNRec(Tree root){
  38. Tree stack[MAXSIZE], node;
  39. int top = 0;
  40. if (root == NULL){
  41. printf("tree is empty-- \n");
  42. return;
  43. }
  44. else{
  45. top++;
  46. // 仿照一个栈
  47. stack[top] = root; // 将根节点入栈
  48. while (top > 0){
  49. //出栈
  50. node = stack[top--];
  51. printf(" %c - ", node->data);
  52. // 先把右子树放进去,栈是先进去后出,所以下面的左子树先出
  53. if (node->right != NULL){
  54. stack[++top] = node->right; // 入栈
  55. }
  56. if (node->left != NULL){
  57. stack[++top] = node->left;
  58. }
  59. }
  60. }
  61. }
  62. // 递归中序遍历二叉树
  63. void inOrderRec(Tree root){
  64. if (root != NULL){
  65. inOrderRec(root->left);
  66. printf(" %c - ", root->data);
  67. inOrderRec(root->right);
  68. }
  69. }
  70. // 非-递归实现中序遍历二叉树
  71. void inOrderNRec(Tree root){
  72. Tree stack[MAXSIZE], node;
  73. int top = 0;
  74. // 判断树是否为空
  75. if (root == NULL){
  76. printf("tree is empty-- \n");
  77. return;
  78. }
  79. node = root;
  80. while (node != NULL || top > 0){
  81. // 将所有的左子树节点入栈
  82. while (node != NULL){
  83. stack[++top] = node;
  84. node = node->left;
  85. }
  86. // 如果右节点为空的话,执行下列语句
  87. node = stack[top--];
  88. printf(" %c - ", node->data);
  89. // 扫描右节点
  90. node = node->right;
  91. }
  92. }
  93. // 递归后序遍历二叉树
  94. void backOrderRec(Tree root){
  95. if (root != NULL){
  96. backOrderRec(root->left);
  97. backOrderRec(root->right);
  98. printf(" %c - ", root->data);
  99. }
  100. }
  101. // 非 - 递归实现后序遍历
  102. void backOrderNRec(Tree root){
  103. Node *p = root;
  104. Node *stack[MAXSIZE];
  105. int num = 0;
  106. Node *have_visited = NULL;
  107. while (NULL != p || num>0)
  108. {
  109. while (NULL != p)
  110. {
  111. stack[num++] = p;
  112. p = p->left;
  113. }
  114. p = stack[num - 1];
  115. if (NULL == p->right || have_visited == p->right)
  116. {
  117. printf(" %c - ", p->data);
  118. num--;
  119. have_visited = p;
  120. p = NULL;
  121. }
  122. else
  123. {
  124. p = p->right;
  125. }
  126. }
  127. }
  128. void backOrderNRecSimple(Tree root){
  129. Tree stack[MAXSIZE], node;
  130. int top = 0;
  131. int count = 0;
  132. char array[MAXSIZE]; // 使用一个数组来保存数据,方便最后数组的反转
  133. if (root == NULL){
  134. printf("tree is empty-- \n");
  135. return;
  136. }
  137. else{
  138. top++;
  139. // 仿照一个栈
  140. stack[top] = root; // 将根节点入栈
  141. while (top > 0){
  142. //出栈
  143. node = stack[top--];
  144. array[count++] = node->data; // 将其保存在一个数组当中
  145. // 先把右子树放进去,栈是先进去后出,所以下面的左子树先出
  146. if (node->left != NULL){
  147. stack[++top] = node->left; // 入栈
  148. }
  149. if (node->right != NULL){
  150. stack[++top] = node->right;
  151. }
  152. }
  153. }
  154. // 反转数组,输出
  155. for (int i = count-1; i >= 0; i--){
  156. printf(" %c - ", array[i]);
  157. }
  158. }
  159. // 层次遍历,打印出二叉树的值
  160. void Level_traversal(Tree root){
  161. if (root == NULL){
  162. printf("tree is empty-- \n");
  163. return;
  164. }
  165. Tree stack[MAXSIZE], node;
  166. node = root;
  167. int front = 0; // 使用 front, rear模拟队列
  168. int rear = 0;
  169. stack[rear++] = node;
  170. while (front != rear){
  171. node = stack[front++]; // 模拟队列,先获取front当前元素,然后在指向 front ++ 位元素
  172. printf(" %c - ", node->data);
  173. // 左右子树入队列
  174. if (node->left != NULL){
  175. stack[rear++] = node->left;
  176. }
  177. if (node->right != NULL){
  178. stack[rear++] = node->right;
  179. }
  180. }
  181. }
  182. int main(){
  183. printf("starting ------ \n");
  184. Tree root = create_tree();
  185. printf("递归前序遍历--- \n");
  186. preOrderRec(root);
  187. printf("\n");
  188. printf("递归中序遍历--- \n");
  189. inOrderRec(root);
  190. printf("\n");
  191. printf("递归后序遍历--- \n");
  192. backOrderRec(root);
  193. printf("\n");
  194. printf("------------------\n");
  195. printf("非递归实现前序遍历--- \n");
  196. preOrderNRec(root);
  197. printf("\n");
  198. printf("非递归实现中序遍历--- \n");
  199. inOrderNRec(root);
  200. printf("\n");
  201. printf("非递归实现后序遍历--- \n");
  202. backOrderNRec(root);
  203. printf("\n");
  204. printf("非递归实现后序遍历 简单的方法 --- \n");
  205. backOrderNRecSimple(root);
  206. printf("\n");
  207. printf("层次遍历 --- \n");
  208. Level_traversal(root);
  209. printf("\n");
  210. // ABD##E##C##
  211. return 0;
  212. }


项目推荐:

2000多G的计算机各行业电子资源分享(持续更新)

2020年微信小程序全栈项目之喵喵交友【附课件和源码】

Spring Boot开发小而美的个人博客【附课件和源码】

Java微服务实战296集大型视频-谷粒商城【附代码和课件】

Java开发微服务畅购商城实战【全357集大项目】-附代码和课件

最全最详细数据结构与算法视频-【附课件和源码】


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

闽ICP备14008679号