二叉树基础--创建、遍历方法(前序/中序/后序/层序、递归/非递归)

  【作者:Dillonn  出处: http://www.cnblogs.com/Dillonn/p/4226929.html  欢迎转载,请务必保留本行】

 

  二叉树的创建及遍历是很多二叉树问题的基础,递归遍历逻辑清晰,代码简约漂亮,然则效率低下(所有递归方案的通病,非不得已不用递归);

  非递归遍历高效,却不是能信手写出来的,特别是后续非递归遍历,相信很多资深码工也有这样的经历:

  5年前学习了二叉树的非递归遍历,一个月前复习了并达到能熟练写出的程度,在不参考任何资料的情况下,今天却怎样也写不出来。

  如果你也有过这种经历,恭喜,这说明你是一个正常人类……

 

  另一方面市面上有些国人写的教材,各种语法、逻辑错误层出不起,不知祸害了多少未来的码工,深感痛心。

  印象比较深刻的有清华大学出版社出版的《数据结果(C++版)》  王红梅、胡明、王涛编著

  如书中第163页后序非递归遍历方法,短短不到30行代码各种语法、逻辑错误如下:  

 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中实现以下方法:

  1.创建一颗二叉树;

      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相应位置的元素的状态:s1、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相应位置的元素的状态:s1、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  欢迎转载,请务必保留本行】

posted @ 2015-01-15 21:19  Dillonn  阅读(1620)  评论(4编辑  收藏  举报