后序遍历的非递归实现

 1 //  实现后序遍历的非递归
 2 //  核心:一个结点需要弹出两次,第一次弹出的时候还需要放回原位(左子树遍历完毕),第二次弹出的时候才输出其值(右子树遍历完毕);
 3 
 4 
 5 #include <iostream>
 6 #include <stack>
 7 using namespace std;
 8 
 9 struct node {
10     int data;
11     struct node* left = nullptr;
12     struct node* right = nullptr;
13     int times = 0;  //当计数值到达2时,不再进入栈中;
14 };
15 
16 typedef struct node node;
17 
18 void init(node& head) {
19     head.data = 1;
20 
21     head.left = new node();
22     head.left->data = 2;
23 
24     head.left->left = new node();
25     head.left->left->data = 3;
26 
27     head.left->left->left = new node();
28     head.left->left->left->data = 4;
29 
30     head.left->right = new node();
31     head.left->right->data = 5;
32 
33     head.left->right->left = new node();
34     head.left->right->left->data = 6;
35 
36     head.right = new node();
37     head.right->data = 7;
38 }
39 
40 int main() {
41     node head;
42 
43     init(head);
44 
45     stack<node*> s;
46 
47     node* p = &head;
48 
49     while (p != nullptr || !s.empty()) {
50         // 入栈
51         if (p != nullptr) {
52             s.push(p);
53             p = p->left;
54         }
55 
56         // 出栈
57         if (p == nullptr) {
58             p = s.top();
59             s.pop();
60 
61             p->times++;
62 
63             //遍历右子树
64             if (p->times == 1) {
65                 s.push(p);
66                 p = p->right;
67             }
68 
69             //p.times==2; 继续弹栈
70             else {
71                 cout << p->data;
72                 p = nullptr;   // 回溯的关键步骤
73             }
74         }
75     }
76 
77     return 0;
78 }

关键点:

  1. 当该结点为非空,进行访问左结点;
  2. 当这个元素出栈时,需要考虑其访问次数:如果次数为1,那么需要将其再次入栈,然后遍历右子树。如果次数为2,那么表示以该节点为跟的子树访问完毕,置为null
  3. 上述的核心遍历代码是对不同的结点以出栈和入栈为单位(遇到非空,进行入栈;遇到空,进行出栈,并进行完整的后序操作),每一次循环对一个结点进行一次完整的操作。  而下列代码主要是以一次操作为单位。
 1 while (p != nullptr || !s.empty()) {
 2         if (p == nullptr) {
 3             p = s.top();
 4             s.pop();
 5             p->times++;
 6         }
 7         else {
 8             // 该结点为根的树已经遍历,相当于NULL 
 9             if (p->times == 2) {
10                 cout << p->data << " ";
11                 p = nullptr;
12             }
13             else if(p->times==1) {
14                 s.push(p);
15                 p = p->right;
16             }
17             else {
18                 s.push(p);
19                 p = p->left;
20             }
21         }
22     }

 

posted @ 2019-09-12 11:06  B_luePhantom  阅读(4540)  评论(0编辑  收藏  举报