二叉树的遍历-中序遍历非递归算法

r囧r小猫 2022-05-26 11:00 245阅读 0赞

70

中序 遍历的几种情况

分析1:什么时候访问根、什么时候访问左子树、什么访问右子树

  1. 当左子树为空或者左子树已经访问完毕以后,再访问根
  2. 访问完毕根以后,再访问右子树。

分析2:为什么是栈,而不是其他队列。

  1. 先走到的后访问、后走到的先访问,显然是栈结构

分析3:结点所有路径情况

步骤1:结点的所有路径情况

如果结点有左子树,该结点入栈;

如果结点没有左子树,访问该结点;

分析3:路径所有情况

如果结点有右子树,重复步骤1;

如果结点没有右子树(结点访问完毕),回退,让栈顶元素出栈,访问栈顶元素,并访问右子树,重复步骤1

如果栈为空,表示遍历结束。

注意:入栈的结点表示,本身没有被访问过,同时右子树也没有被访问过。

分析4:有一个一直往左走入栈的操作

我的理解:先遍历到结点B,发现B没有左子树,故访问B,打印B;接着遍历看B的右子树,发现结点C,有左子树D,故C入栈,继续遍历D,发现结点D没有左子树,故访问D,打印D,接着发现结点D没有右子树,回退,让栈顶元素出栈,此时栈中有C,出栈,打印出来C,回退遍历到结点A,A有右子树,遍历结点E,E结点没有左子树,访问E,打印出来,E有右子树,遍历到F结点,F结点有左子树G,故F入栈,接着遍历到G结点,发现G有左子树H结点,故G入栈,遍历到H结点,H没有左子树,故访问H,打印出来H,H没有有右子树,回退,让栈顶元素出栈,也就是G。遍历I结点,因为I没有左子树,故访问I,打印出来I结点,I没有右子树,回退,让栈顶元素出栈,也就是F,栈中为NULL,表示遍历结束

  1. #include <iostream>
  2. using namespace std;
  3. #include "stack"
  4. //二叉链表示法
  5. typedef struct BiTNode
  6. {
  7. char data;//数据域
  8. struct BiTNode *lchild;//指针域,存放指向左孩子的指针
  9. struct BiTNode *rchild;//指针域,存放指向右孩子的指针
  10. }BiTNode, *BiTree;
  11. /*
  12. 步骤1:
  13. 如果结点有左子树,该结点入栈;
  14. 如果结点没有左子树,访问该结点;
  15. 步骤2:
  16. 如果结点有右子树,重复步骤1;
  17. 如果结点没有右子树(结点访问完毕),根据栈顶指示回退,访问栈顶元素,并访问右子树,重复步骤1
  18. 如果栈为空,表示遍历结束。
  19. */
  20. //一直往左边走,找到中序遍历的起点
  21. BiTNode *goLeft(BiTNode *T, stack<BiTNode *> &s)
  22. {
  23. if (NULL == T)
  24. {
  25. return NULL;
  26. }
  27. //判断T有没有左孩子,没有把T 返回
  28. //有,T入栈
  29. while (T->lchild !=NULL)
  30. {
  31. s.push(T);
  32. T = T->lchild;
  33. }
  34. return T;
  35. }
  36. void Inorder2(BiTNode *T)
  37. {
  38. BiTNode *t = NULL;
  39. stack<BiTNode *> s;
  40. t = goLeft(T,s);
  41. while (t)
  42. {
  43. //如果结点没有左子树,访问该结点;打印该结点数据
  44. printf("%c ", t->data);
  45. //如果t 有右子树 重复步骤1
  46. if (t->rchild !=NULL)
  47. {
  48. t = goLeft(t->rchild,s);//右子树中中序遍历的起点
  49. }
  50. else if (!s.empty())//如果t没有右子树 根据栈顶指示 回退
  51. {
  52. t = s.top();//获得栈顶元素
  53. s.pop();//将其弹出
  54. }
  55. else//如果t没有右子树 并且栈为空
  56. {
  57. t = NULL;
  58. }
  59. }
  60. }
  61. void inOrder(BiTNode *root)
  62. {
  63. if (root == NULL)
  64. {
  65. return;
  66. }
  67. //遍历左子树
  68. inOrder(root->lchild);
  69. printf("%c ", root->data);
  70. //遍历右子树
  71. inOrder(root->rchild);
  72. }
  73. void main()
  74. {
  75. BiTNode A, B, C, D, E, F, G, H, I;
  76. memset(&A, 0, sizeof(BiTNode));
  77. memset(&B, 0, sizeof(BiTNode));
  78. memset(&C, 0, sizeof(BiTNode));
  79. memset(&D, 0, sizeof(BiTNode));
  80. memset(&E, 0, sizeof(BiTNode));
  81. memset(&F, 0, sizeof(BiTNode));
  82. memset(&G, 0, sizeof(BiTNode));
  83. memset(&H, 0, sizeof(BiTNode));
  84. memset(&I, 0, sizeof(BiTNode));
  85. A.data = 'A';
  86. B.data = 'B';
  87. C.data = 'C';
  88. D.data = 'D';
  89. E.data = 'E';
  90. F.data = 'F';
  91. G.data = 'G';
  92. H.data = 'H';
  93. I.data = 'I';
  94. //建立关系
  95. A.lchild = &B;
  96. A.rchild = &E;
  97. E.rchild = &F;
  98. F.lchild = &G;
  99. G.lchild = &H;
  100. G.rchild = &I;
  101. B.rchild = &C;
  102. C.lchild = &D;
  103. printf("\nolder inorder\n");
  104. inOrder(&A);
  105. printf("\n 非递归遍历\n");
  106. Inorder2(&A);
  107. printf("hello...\n");
  108. system("pause");
  109. return;
  110. }

发表评论

表情:
评论列表 (有 0 条评论,245人围观)

还没有评论,来说两句吧...

相关阅读