二叉樹的四種遍歷方法(遞歸、迭代)


一、前序遍歷

前序遍歷簡單來講,遍歷順序是:根節點-左子樹-右子樹

1、遞歸遍歷

1 void preorder(BinTree *T)
2 {
3     if(T==NULL)
4         return;
5     cout << T->data;
6     preorder(T->left);
7     preorder(T->right);
8 }

2、迭代遍歷(用棧實現)

 1 void preorder2(BinTree *T)
 2 {
 3     //空樹,直接返回
 4     if(T==NULL)
 5         return;
 6     //定義一個存放二叉樹節點的棧結構
 7     stack<BinTree*>s;
 8     BinTree *pcur; 
 9     pcur = T;
10     //循環遍歷二叉樹直到根節點為空或者棧為空
11     while (pcur || !s.empty())
12     {
13         if (pcur)
14         {
15             cout << pcur->data;
16             s.push(pcur);
17             pcur = pcur->left;
18         }else
19         {
20             //當根節點為空時,說明左子樹已遍歷完,通過取出棧頂結點,來訪問根節點的右子樹
21             pcur = s.top();
22             s.pop();
23             pcur = pcur->right;
24         }
25     }
26 }

二、中序遍歷

遍歷順序是:左子樹-根節點-右子樹

1、遞歸遍歷

1 void inoeder(BinTree *T)
2 {
3     if(T == NULL)
4         return;
5     inoeder(T->left);
6     cout << T->data;
7     inoeder(T->right);
8 }

2、迭代遍歷(用棧實現)

 1 void inorder2(BinTree *T)
 2 {
 3     if(T == NULL)
 4         return;
 5     stack<BinTree*>s;
 6     BinTree *pcur;
 7     pcur = T;
 8     while (pcur || !s.empty())
 9     {
10         if (pcur)
11         {
12             //根節點非空,入棧,繼續遍歷左子樹直到根節點為空
13             s.push(pcur);
14             pcur = pcur->left;
15         }else
16         {
17             //根節點為空,說明左子樹已經遍歷完,彈出根節點打印,通過根節點訪問右子樹
18             pcur = s.top();
19             s.pop();
20             cout << pcur->data;
21             pcur = pcur->right;            
22         }
23     }
24 }

三、后序遍歷

遍歷順序:左子樹-右子樹-根節點

1、遞歸遍歷

1 void postorder(BinTree *T)
2 {
3     if (T==NULL)
4         return;
5     postorder(T->left);
6     postorder(T->right);
7     cout << T->data;
8 }

2、迭代遍歷(用棧實現)

 1 void postorder2(BinTree *T)
 2 {
 3     if(T == NULL)
 4         return;
 5     stack<BinTree*>s;
 6     s.push(T);
 7     BinTree *pcur;
 8     pcur = NULL;
 9     while (!s.empty())
10     {
11         pcur = s.top();
12         if (pcur->left == NULL && pcur->right == NULL)
13         {
14             cout << pcur->data;
15             s.pop();
16         }else
17         {
18             //注意右孩子先入棧左孩子后入棧,這樣再次循環時左孩子節點才先出棧
19             if(pcur->right)
20             {
21                 s.push(pcur->right);
22                 pcur->right = NULL;
23             }
24             if (pcur->left)
25             {
26                 s.push(pcur->left);
27                 pcur->left = NULL;
28             }    
29         }
30     }
31 }

四、層序遍歷

層序遍歷是圖的廣度優先搜索的應用,常用隊列結構實現

1.迭代遍歷

關鍵點:根節點一出隊列,就要判斷其左右孩子是否為空,若不為空的話依次入隊列

 1 void leveltraversal(BinTree *T)
 2 {
 3     queue<BinTree*> s;
 4     s.push(T);
 5     BinTree* pcur;
 6     while (!s.empty())
 7     {
 8         pcur=s.front();
 9         cout<<pcur->data;
10         s.pop();
11         if (pcur->left)
12         {
13             s.push(pcur->left);
14         }
15         if (pcur->right)
16         {
17             s.push(pcur->right);
18         }
19     }    
20 }

 2、分層遍歷二叉樹,即從上到下按層次訪問該樹,每一層單獨輸出一行

思想:定義兩個變量last,nlast,last代表正在打印的當前行的最右節點,nlast代表目前出現的進入隊列的最右節點(下一行節點),nlast跟蹤的是隊列中加入的節點。

                                                   

last等於節點1,1入隊列,打印1並彈出1,將1的左右孩子放入隊列,2入隊列,並讓nlast等於節點2,3入隊列並讓nlast等於節點3,此時發現last與之前出隊列的1節點相等,換行,並將nlast賦給last(等於節點3)。

接下來,節點2出棧,打印節點2,並讓結點2的孩子進入隊列,節點4進入隊列並讓nlast等於節點4,節點3出隊列並打印節點3,讓節點3的孩子進入隊列,節點5進入隊列並讓nlast等於節點5,節點6進入隊列並讓nlast等於節點6,此時發現last與上次出隊列的節點3相等,於是換行,並將nlast賦給last(等於節點6),接下來類此。

 1 void leveltraversal3(BinTree *T)
 2 {
 3     if(T == NULL)
 4         return;
 5     queue<BinTree*>s;
 6     s.push(T);
 7     BinTree *pcur,*last,*nlast;
 8     last = T;
 9     nlast = NULL;
10     while (!s.empty())
11     {
12         pcur = s.front();
13         cout << pcur->data;
14         s.pop();        
15         if (pcur->left)
16         {
17             s.push(pcur->left);
18             nlast = pcur->left;
19         }
20         if (pcur->right)
21         {
22             s.push(pcur->right);
23             nlast = pcur->right;
24         }
25         if (last == pcur)
26         {
27             cout << endl;
28             last = nlast;
29         }            
30     }
31 }

 


免責聲明!

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



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