后序遍歷的非遞歸實現


 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     }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM