二叉樹基礎--建立、遍歷方法(前序/中序/後序/層序、遞歸/非遞歸)

  【做者:Dillonn  出處: http://www.cnblogs.com/Dillonn/p/4226929.html  歡迎轉載,請務必保留本行】html

 

  二叉樹的建立及遍歷是不少二叉樹問題的基礎,遞歸遍歷邏輯清晰,代碼簡約漂亮,然則效率低下(全部遞歸方案的通病,非不得已不用遞歸);ios

  非遞歸遍歷高效,卻不是能信手寫出來的,特別是後續非遞歸遍歷,相信不少資深碼工也有這樣的經歷:ide

  5年前學習了二叉樹的非遞歸遍歷,一個月前複習了並達到能熟練寫出的程度,在不參考任何資料的狀況下,今天卻怎樣也寫不出來。函數

  若是你也有過這種經歷,恭喜,這說明你是一個正常人類……post

 

  另外一方面市面上有些國人寫的教材,各類語法、邏輯錯誤層出不起,不知禍害了多少將來的碼工,深感痛心。學習

  印象比較深入的有清華大學出版社出版的《數據結果(C++版)》  王紅梅、胡明、王濤編著spa

  如書中第163頁後序非遞歸遍歷方法,短短不到30行代碼各類語法、邏輯錯誤以下:  code

 1 template <typename T>
 2 void BiTree::PostOrder(BiNode<T> * root)//錯誤一:正確的寫法爲void BiTree<T>::PostOrder(BiNode<T> * root)
 3 {
 4     top = -1;
 5     //錯誤二:應該在這裏定義下文用到的棧s(書中說這是具體的代碼,不是僞代碼)。
 6     wihle(root != NULL || top != -1)
 7     {
 8         while(root != NULL)
 9         {
10             top++;
11             s[top].ptr = root;
12             s[top].flag = 1;
13             root = root -> lchild;
14         }
15         while(top != -1 && s[top].flag ==2)
16         {
17             root = s[top--].ptr;
18             cout << root->data;
19         }
20         if(top != -1)
21         {
22             s[top].flag = 2;
23             root = s[top].ptr->rchild;
24         }
25         //錯誤三:致命邏輯錯誤,棧空時,遍歷結束,退出外層循環或函數返回,不然將進入死循環,應該加上以下一行代碼。
26         else break;//書中沒有這一行
27     }
28 }

 

  下面我們來實現一個二叉樹Class,在Class中實現如下方法:htm

  1.建立一顆二叉樹;blog

      2.銷燬一顆二叉樹;

  3.遞歸前序遍歷方法;

  4.非遞歸前序遍歷方法;

  5.遞歸中序遍歷方法;

  6.非遞歸中序遍歷方法;

  7.遞歸後序遍歷方法;

  8.非遞歸後序遍歷方法;

  9.層序遍歷方法(這個應該就沒有遞歸的方法)。

 

   要點:非遞歸遍歷用棧輔助(深度優先),層序遍歷用隊列輔助(廣度優先)。  

 

  二叉樹節點定義:   

1 template <typename T>
2 struct BiNode
3 {
4     T data;
5     BiNode<T> *pLeft;
6     BiNode<T> *pRight;
7 };

  

  二叉樹Class定義: 

  要點:1.數據成員申明爲私有;

     2. 公有成員方法如PreOrder1()爲對外接口,調用私有成員方法PreOrderRecursive(BiNode<T> * root)實現其具體功能。

 1 template <typename T>
 2 class BiTree
 3 {
 4     public:
 5         BiTree();
 6         ~BiTree();
 7         void PreOrder1();//遞歸
 8         void PreOrder2();//非遞歸
 9         void InOrder1();//遞歸
10         void InOrder2();//非遞歸
11         void PostOrder1();//遞歸
12         void PostOrder2();//非遞歸
13         void LevelOrder();
14     private:
15         BiNode<T> * root;
16         void CreateBiTree(BiNode<T> * &root);
17         void ReleaseBiTree(BiNode<T> * root);
18         
19         void PreOrderRecursive(BiNode<T> * root);
20         void PreOrderNonRecursive(BiNode<T> * root);
21         
22         void InOrderRecursive(BiNode<T> * root);
23         void InOrderNonRecursive(BiNode<T> * root);
24         
25         void PostOrderRecursive(BiNode<T> * root);
26         void PostOrderNonRecursive(BiNode<T> * root);
27         
28         void LevelOrder(BiNode<T> * root);
29 };

  

  建立二叉樹:

 1 template <typename T>
 2 void BiTree<T>::CreateBiTree( BiNode<T> * &root)// 根據前序遍歷次序建立二叉樹
 3 {
 4     T data;
 5     cin>>data;
 6     if(data == INVALID)
 7     {
 8         root = NULL;
 9     }
10     else
11     {
12         root = new BiNode<T>;
13         root->data = data;
14         CreateBiTree(root->pLeft);
15         CreateBiTree(root->pRight);
16     }
17 }
18 
19 
20 template <typename T>
21 BiTree<T>::BiTree():root(NULL)
22 {
23     CreateBiTree(root);
24 }

 

  銷燬二叉樹:  

 1 template <typename T>
 2 void BiTree<T>::ReleaseBiTree(BiNode<T> * root)
 3 {
 4     if(root != NULL)
 5     {
 6         ReleaseBiTree(root->pLeft);
 7         ReleaseBiTree(root->pRight);
 8         delete root;
 9     }
10 }
11 
12 
13 template <typename T>
14 BiTree<T>::~BiTree()
15 {
16     ReleaseBiTree(root);
17 }

 

  前序遞歸遍歷:  

 1 template <typename T>
 2 void BiTree<T>::PreOrderRecursive(BiNode<T> * root)
 3 {
 4     if(root != NULL)
 5     {
 6         cout<<root->data<<" ";
 7         PreOrderRecursive(root->pLeft);
 8         PreOrderRecursive(root->pRight);
 9     }
10 }
11 
12 
13 
14 template <typename T>
15 void BiTree<T>::PreOrder1()
16 {
17     PreOrderRecursive(root);
18     cout<<endl;
19 }

  

  中序遞歸遍歷:

 1 template <typename T>
 2 void BiTree<T>::InOrderRecursive(BiNode<T> * root)
 3 {
 4     if(root != NULL)
 5     {
 6         InOrderRecursive(root->pLeft);
 7         cout<<root->data<<" ";
 8         InOrderRecursive(root->pRight);
 9     }
10 }
11 
12 
13 template <typename T>
14 void BiTree<T>::InOrder1()
15 {
16     InOrderRecursive(root);
17     cout<<endl;
18 }

  

  後序遞歸遍歷:  

 1 template <typename T>
 2 void BiTree<T>::PostOrderRecursive(BiNode<T> * root)
 3 {
 4     if(root != NULL)
 5     {
 6                 PostOrderRecursive(root->pLeft);
 7                 PostOrderRecursive(root->pRight);
 8                 cout<<root->data<<" ";
 9     }
10 }
11 
12 
13 template <typename T>
14 void BiTree<T>::PostOrder1()
15 {
16     PostOrderRecursive(root);
17     cout<<endl;
18 }

  

  層序遍歷:  

 1 template <typename T>
 2 void BiTree<T>::LevelOrder(BiNode<T> * root)
 3 {    
 4     BiNode<T> * p;
 5     queue<BiNode<T> *> q;
 6     if(root == NULL) 
 7         return;
 8     q.push(root);
 9     while(!q.empty())
10     {
11         p = q.front();
12         cout << p->data<<" ";
13         q.pop();
14         if(p->pLeft != NULL) q.push(p->pLeft);
15         if(p->pRight != NULL) q.push(p->pRight);
16     }
17 }
18 
19 template <typename T>
20 void BiTree<T>::LevelOrder()
21 {
22     LevelOrder(root);
23     cout<<endl;
24 }

 

  前序非遞歸遍歷:

 1 template <typename T>
 2 void BiTree<T>:: PreOrderNonRecursive(BiNode<T> * root)
 3 {
 4     stack<BiNode<T> *> s;
 5     while(root != NULL || !s.empty())
 6     {
 7         while(root != NULL)
 8         {
 9             cout<<root->data<<" ";
10             s.push(root);
11             root = root->pLeft; 
12         }
13         if(!s.empty())
14         {
15             root = s.top();
16             s.pop();
17             root = root->pRight;
18         }
19     }
20                     
21 }
22 
23 
24 
25 
26 template <typename T>
27 void BiTree<T>::PreOrder2()
28 {
29     PreOrderNonRecursive(root);
30     cout<<endl;
31 }

 

  中序非遞歸遍歷:  

 1 template <typename T>
 2 void BiTree<T>::InOrderNonRecursive(BiNode<T> * root)
 3 {
 4     stack<BiNode<T> *> s;
 5     while(root != NULL || !s.empty())
 6     {
 7         while(root != NULL)
 8         {
 9             s.push(root);
10             root = root->pLeft; 
11         }
12         if(!s.empty())
13         {
14             root = s.top();
15             s.pop();
16             cout<<root->data<<" ";            
17             root = root->pRight;
18         }
19     }
20                     
21 }
22 
23 
24 
25 template <typename T>
26 void BiTree<T>::InOrder2()
27 {
28     InOrderNonRecursive(root);
29     cout<<endl;
30 }

 

  後序非遞歸遍歷:

 1 template <typename T>
 2 void BiTree<T>::PostOrderNonRecursive(BiNode<T> * root)
 3 {
 4 
 5     stack<BiNode<T> *> s1;
 6     stack<int> s2;//s2輔助記錄s1相應位置的元素的狀態:s一、s2保持同步。
 7             
 8     while(root != NULL || !s1.empty())
 9     {
10         while(root != NULL)
11         {
12             s1.push(root);
13             s2.push(1);
14             root = root->pLeft;
15         }
16         if(!s1.empty())
17         {
18             if(s2.top()==1)
19             {
20                 s2.pop();
21                 s2.push(2);
22                 root = s1.top()->pRight;
23             }
24             else
25             {
26                 root = s1.top();
27                 s1.pop();
28                 s2.pop();
29                 cout<<root->data<<" ";
30                 root = NULL;    
31             }
32         }
33         
34     }
35             
36 }
37 
38 
39 
40 template <typename T>
41 void BiTree<T>::PostOrder2()
42 {
43     PostOrderNonRecursive(root);
44     cout<<endl;
45 }

 

  假定咱們建立的二叉樹形狀以下:

 1 /*
 2 假定所建立的二叉樹以下圖所示
 3                                              A
 4                                            /   \
 5                                           B     C
 6                                          / \    /
 7                                         D   E  F
 8                                              \
 9                                               G
10 
11 
12 建立二叉樹的文件:《BiTree.txt》內容以下:
13 A B D # # E # G # # C  F # # #
14 
15 */
16 const char *preorder  = "A B D E G C F";
17 const char *inorder   = "D B E G A F C";
18 const char *postorder = "D G E B F C A";
19 const char *levelorder= "A B C D E F G";

  

  main函數:

 1 int main()
 2 {
 3     ifstream fin("BiTree.txt");// 輸入文件
 4     ofstream fout("out.txt");  //輸出文件
 5 
 6     streambuf *cinbackup;
 7     streambuf *coutbackup;
 8 
 9     cinbackup= cin.rdbuf(fin.rdbuf());  //用 rdbuf() 從新定向
10     coutbackup= cout.rdbuf(fout.rdbuf());  //用 rdbuf() 從新定向
11 
12     BiTree<char> *pbitree = new BiTree<char>;//建立一顆二叉樹
13     
14     cout << "*preorder =   " << preorder << endl;
15     cout << " PreOrder1(): ";
16     pbitree->PreOrder1();
17     cout << " PreOrder2(): ";
18     pbitree->PreOrder2();
19     cout<<endl;
20     
21     cout << "*inorder =   " << inorder << endl;
22     cout << " inorder1(): ";
23     pbitree->InOrder1();
24     cout << " InOrder2(): ";
25     pbitree->InOrder2();
26     cout<<endl;
27     
28     cout << "*postorder =   " << postorder << endl;
29     cout << " PostOrder1(): ";
30     pbitree->PostOrder1();    
31     cout << " PostOrder2(): ";
32     pbitree->PostOrder2();
33     cout<<endl;
34     
35     cout << "*levelorder =  " << levelorder << endl;
36     cout << " LevelOrder(): ";
37     pbitree->LevelOrder();
38 
39     delete pbitree;
40     cin.rdbuf(cinbackup);  // 取消,恢復鍵盤輸入
41     cout.rdbuf(coutbackup);  //取消,恢復屏幕輸出
42     return 0;
43 }

  

  MVS2005上的運行結果以下圖:

 

  完整的代碼: 

  1 #include <iostream>
  2 #include <fstream>
  3 #include <stack>
  4 #include <queue>
  5 
  6 using namespace std;
  7 
  8 
  9 /*
 10 假定所建立的二叉樹以下圖所示
 11                                              A
 12                                            /   \
 13                                           B     C
 14                                          / \    /
 15                                         D   E  F
 16                                              \
 17                                               G
 18 
 19 
 20 建立二叉樹的文件:《BiTree.txt》內容以下:
 21 A B D # # E # G # # C  F # # #
 22 
 23 */
 24 const char *preorder  = "A B D E G C F";
 25 const char *inorder   = "D B E G A F C";
 26 const char *postorder = "D G E B F C A";
 27 const char *levelorder= "A B C D E F G";
 28 
 29 const char INVALID = '#';//INVALID在CreateBiTree()函數中表示空節點,類型適配 template <typename T>
 30 
 31 template <typename T>
 32 struct BiNode
 33 {
 34     T data;
 35     BiNode<T> *pLeft;
 36     BiNode<T> *pRight;
 37 //    BiNode():data(0){cout<<"BiNode Constructor"<<endl;};
 38 //    ~BiNode(){cout<<"BiNode Destructor"<<endl;};
 39 };
 40 
 41 template <typename T>
 42 class BiTree
 43 {
 44     public:
 45         BiTree();
 46         ~BiTree();
 47         void PreOrder1();//遞歸
 48         void PreOrder2();//非遞歸
 49         void InOrder1();//遞歸
 50         void InOrder2();//非遞歸
 51         void PostOrder1();//遞歸
 52         void PostOrder2();//非遞歸
 53         void LevelOrder();
 54     private:
 55         BiNode<T> * root;
 56         void CreateBiTree(BiNode<T> * &root);
 57         void ReleaseBiTree(BiNode<T> * root);
 58         
 59         void PreOrderRecursive(BiNode<T> * root);
 60         void PreOrderNonRecursive(BiNode<T> * root);
 61         
 62         void InOrderRecursive(BiNode<T> * root);
 63         void InOrderNonRecursive(BiNode<T> * root);
 64         
 65         void PostOrderRecursive(BiNode<T> * root);
 66         void PostOrderNonRecursive(BiNode<T> * root);
 67         
 68         void LevelOrder(BiNode<T> * root);
 69 };
 70 
 71 
 72 template <typename T>
 73 void BiTree<T>::CreateBiTree( BiNode<T> * &root)// 根據前序遍歷次序建立二叉樹
 74 {
 75     T data;
 76     cin>>data;
 77     if(data == INVALID)
 78     {
 79         root = NULL;
 80     }
 81     else
 82     {
 83         root = new BiNode<T>;
 84         root->data = data;
 85         CreateBiTree(root->pLeft);
 86         CreateBiTree(root->pRight);
 87     }
 88 }
 89 
 90 
 91 template <typename T>
 92 void BiTree<T>::ReleaseBiTree(BiNode<T> * root)
 93 {
 94     if(root != NULL)
 95     {
 96         ReleaseBiTree(root->pLeft);
 97         ReleaseBiTree(root->pRight);
 98         delete root;
 99     }
100 }
101 
102 
103 template <typename T>
104 BiTree<T>::BiTree():root(NULL)
105 {
106     CreateBiTree(root);
107 }
108 
109 
110 template <typename T>
111 BiTree<T>::~BiTree()
112 {
113     ReleaseBiTree(root);
114 }
115 
116 
117 template <typename T>
118 void BiTree<T>::PreOrderRecursive(BiNode<T> * root)
119 {
120     if(root != NULL)
121     {
122         cout<<root->data<<" ";
123         PreOrderRecursive(root->pLeft);
124         PreOrderRecursive(root->pRight);
125     }
126 }
127 
128 
129 template <typename T>
130 void BiTree<T>:: PreOrderNonRecursive(BiNode<T> * root)
131 {
132     stack<BiNode<T> *> s;
133     while(root != NULL || !s.empty())
134     {
135         while(root != NULL)
136         {
137             cout<<root->data<<" ";
138             s.push(root);
139             root = root->pLeft; 
140         }
141         if(!s.empty())
142         {
143             root = s.top();
144             s.pop();
145             root = root->pRight;
146         }
147     }
148                     
149 }
150 
151 
152 template <typename T>
153 void BiTree<T>::PreOrder1()
154 {
155     PreOrderRecursive(root);
156     cout<<endl;
157 }
158 
159 
160 template <typename T>
161 void BiTree<T>::PreOrder2()
162 {
163     PreOrderNonRecursive(root);
164     cout<<endl;
165 }
166 
167 
168 template <typename T>
169 void BiTree<T>::InOrderRecursive(BiNode<T> * root)
170 {
171     if(root != NULL)
172     {
173         InOrderRecursive(root->pLeft);
174         cout<<root->data<<" ";
175         InOrderRecursive(root->pRight);
176     }
177 }
178 
179 
180 template <typename T>
181 void BiTree<T>::InOrderNonRecursive(BiNode<T> * root)
182 {
183     stack<BiNode<T> *> s;
184     while(root != NULL || !s.empty())
185     {
186         while(root != NULL)
187         {
188             s.push(root);
189             root = root->pLeft; 
190         }
191         if(!s.empty())
192         {
193             root = s.top();
194             s.pop();
195             cout<<root->data<<" ";            
196             root = root->pRight;
197         }
198     }
199                     
200 }
201 
202 
203 template <typename T>
204 void BiTree<T>::InOrder1()
205 {
206     InOrderRecursive(root);
207     cout<<endl;
208 }
209 
210 
211 template <typename T>
212 void BiTree<T>::InOrder2()
213 {
214     InOrderNonRecursive(root);
215     cout<<endl;
216 }
217 
218 
219 template <typename T>
220 void BiTree<T>::PostOrderRecursive(BiNode<T> * root)
221 {
222     if(root != NULL)
223     {
224                 PostOrderRecursive(root->pLeft);
225                 PostOrderRecursive(root->pRight);
226                 cout<<root->data<<" ";
227     }
228 }
229 
230 
231 template <typename T>
232 void BiTree<T>::PostOrderNonRecursive(BiNode<T> * root)
233 {
234 
235     stack<BiNode<T> *> s1;
236     stack<int> s2;//s2輔助記錄s1相應位置的元素的狀態:s一、s2保持同步。
237             
238     while(root != NULL || !s1.empty())
239     {
240         while(root != NULL)
241         {
242             s1.push(root);
243             s2.push(1);
244             root = root->pLeft;
245         }
246         if(!s1.empty())
247         {
248             if(s2.top()==1)
249             {
250                 s2.pop();
251                 s2.push(2);
252                 root = s1.top()->pRight;
253             }
254             else
255             {
256                 root = s1.top();
257                 s1.pop();
258                 s2.pop();
259                 cout<<root->data<<" ";
260                 root = NULL;    
261             }
262         }
263         
264     }
265             
266 }
267 
268 
269 template <typename T>
270 void BiTree<T>::PostOrder1()
271 {
272     PostOrderRecursive(root);
273     cout<<endl;
274 }
275 
276 
277 template <typename T>
278 void BiTree<T>::PostOrder2()
279 {
280     PostOrderNonRecursive(root);
281     cout<<endl;
282 }
283 
284 
285 template <typename T>
286 void BiTree<T>::LevelOrder(BiNode<T> * root)
287 {    
288     BiNode<T> * p;
289     queue<BiNode<T> *> q;
290     if(root == NULL) 
291         return;
292     q.push(root);
293     while(!q.empty())
294     {
295         p = q.front();
296         cout << p->data<<" ";
297         q.pop();
298         if(p->pLeft != NULL) q.push(p->pLeft);
299         if(p->pRight != NULL) q.push(p->pRight);
300     }
301 }
302 
303 
304 template <typename T>
305 void BiTree<T>::LevelOrder()
306 {
307     LevelOrder(root);
308     cout<<endl;
309 }
310 
311 
312 
313 int main()
314 {
315 
316 
317     ifstream fin("BiTree.txt");// 輸入文件
318     ofstream fout("out.txt");  //輸出文件
319 
320     streambuf *cinbackup;
321     streambuf *coutbackup;
322 
323     cinbackup= cin.rdbuf(fin.rdbuf());  //用 rdbuf() 從新定向
324     coutbackup= cout.rdbuf(fout.rdbuf());  //用 rdbuf() 從新定向
325 
326     BiTree<char> *pbitree = new BiTree<char>;//建立一顆二叉樹
327     
328     cout << "*preorder =   " << preorder << endl;
329     cout << " PreOrder1(): ";
330     pbitree->PreOrder1();
331     cout << " PreOrder2(): ";
332     pbitree->PreOrder2();
333     cout<<endl;
334     
335     cout << "*inorder =   " << inorder << endl;
336     cout << " inorder1(): ";
337     pbitree->InOrder1();
338     cout << " InOrder2(): ";
339     pbitree->InOrder2();
340     cout<<endl;
341     
342     cout << "*postorder =   " << postorder << endl;
343     cout << " PostOrder1(): ";
344     pbitree->PostOrder1();    
345     cout << " PostOrder2(): ";
346     pbitree->PostOrder2();
347     cout<<endl;
348     
349     cout << "*levelorder =  " << levelorder << endl;
350     cout << " LevelOrder(): ";
351     pbitree->LevelOrder();
352 
353     delete pbitree;
354     cin.rdbuf(cinbackup);  // 取消,恢復鍵盤輸入
355     cout.rdbuf(coutbackup);  //取消,恢復屏幕輸出
356     return 0;
357 }
View Code

 

 

  【做者:Dillonn  出處: http://www.cnblogs.com/Dillonn/p/4226929.html  歡迎轉載,請務必保留本行】

相關文章
相關標籤/搜索