码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-01-15 21:45:57      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:

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

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

  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.数据成员申明为私有(原因见Effective C++ 条款21:将成员变量申明为private);

     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 template <typename T>
39 void BiTree<T>::PostOrder1()
40 {
41     PostOrderRecursive(root);
42     cout<<endl;
43 }
44 
45 template <typename T>
46 void BiTree<T>::PostOrder2()
47 {
48     PostOrderNonRecursive(root);
49     cout<<endl;
50 }

  

  假定我们创建的二叉树形状如下:

 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 G";
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 }

  

  VC2005上的运行结果如下图:

  技术分享

 

  完整的代码:  

  

技术分享
  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 G";
 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 };
 38 
 39 template <typename T>
 40 class BiTree
 41 {
 42     public:
 43         BiTree();
 44         ~BiTree();
 45         void PreOrder1();//递归
 46         void PreOrder2();//非递归
 47         void InOrder1();//递归
 48         void InOrder2();//非递归
 49         void PostOrder1();//递归
 50         void PostOrder2();//非递归
 51         void LevelOrder();
 52     private:
 53         BiNode<T> * root;
 54         void CreateBiTree(BiNode<T> * &root);
 55         void ReleaseBiTree(BiNode<T> * root);
 56         
 57         void PreOrderRecursive(BiNode<T> * root);
 58         void PreOrderNonRecursive(BiNode<T> * root);
 59         
 60         void InOrderRecursive(BiNode<T> * root);
 61         void InOrderNonRecursive(BiNode<T> * root);
 62         
 63         void PostOrderRecursive(BiNode<T> * root);
 64         void PostOrderNonRecursive(BiNode<T> * root);
 65         
 66         void LevelOrder(BiNode<T> * root);
 67 };
 68 
 69 
 70 template <typename T>
 71 void BiTree<T>::CreateBiTree( BiNode<T> * &root)// 根据前序遍历次序创建二叉树
 72 {
 73     T data;
 74     cin>>data;
 75     if(data == INVALID)
 76     {
 77         root = NULL;
 78     }
 79     else
 80     {
 81         root = new BiNode<T>;
 82         root->data = data;
 83         CreateBiTree(root->pLeft);
 84         CreateBiTree(root->pRight);
 85     }
 86 }
 87 
 88 
 89 template <typename T>
 90 void BiTree<T>::ReleaseBiTree(BiNode<T> * root)
 91 {
 92     if(root != NULL)
 93     {
 94         ReleaseBiTree(root->pLeft);
 95         ReleaseBiTree(root->pRight);
 96         delete root;
 97     }
 98 }
 99 template <typename T>
100 BiTree<T>::BiTree():root(NULL)
101 {
102     CreateBiTree(root);
103 }
104 
105 
106 template <typename T>
107 BiTree<T>::~BiTree()
108 {
109     ReleaseBiTree(root);
110 }
111 
112 
113 template <typename T>
114 void BiTree<T>::PreOrderRecursive(BiNode<T> * root)
115 {
116     if(root != NULL)
117     {
118         cout<<root->data<<" ";
119         PreOrderRecursive(root->pLeft);
120         PreOrderRecursive(root->pRight);
121     }
122 }
123 
124 template <typename T>
125 void BiTree<T>:: PreOrderNonRecursive(BiNode<T> * root)
126 {
127     stack<BiNode<T> *> s;
128     while(root != NULL || !s.empty())
129     {
130         while(root != NULL)
131         {
132             cout<<root->data<<" ";
133             s.push(root);
134             root = root->pLeft; 
135         }
136         if(!s.empty())
137         {
138             root = s.top();
139             s.pop();
140             root = root->pRight;
141         }
142     }
143                     
144 }
145 
146 
147 template <typename T>
148 void BiTree<T>::PreOrder1()
149 {
150     PreOrderRecursive(root);
151     cout<<endl;
152 }
153 
154 template <typename T>
155 void BiTree<T>::PreOrder2()
156 {
157     PreOrderNonRecursive(root);
158     cout<<endl;
159 }
160 
161 template <typename T>
162 void BiTree<T>::InOrderRecursive(BiNode<T> * root)
163 {
164     if(root != NULL)
165     {
166         InOrderRecursive(root->pLeft);
167         cout<<root->data<<" ";
168         InOrderRecursive(root->pRight);
169     }
170 }
171 
172 template <typename T>
173 void BiTree<T>::InOrderNonRecursive(BiNode<T> * root)
174 {
175     stack<BiNode<T> *> s;
176     while(root != NULL || !s.empty())
177     {
178         while(root != NULL)
179         {
180             s.push(root);
181             root = root->pLeft; 
182         }
183         if(!s.empty())
184         {
185             root = s.top();
186             s.pop();
187             cout<<root->data<<" ";            
188             root = root->pRight;
189         }
190     }
191                     
192 }
193 
194 template <typename T>
195 void BiTree<T>::InOrder1()
196 {
197     InOrderRecursive(root);
198     cout<<endl;
199 }
200 
201 
202 template <typename T>
203 void BiTree<T>::InOrder2()
204 {
205     InOrderNonRecursive(root);
206     cout<<endl;
207 }
208 
209 template <typename T>
210 void BiTree<T>::PostOrderRecursive(BiNode<T> * root)
211 {
212     if(root != NULL)
213     {
214                 PostOrderRecursive(root->pLeft);
215                 PostOrderRecursive(root->pRight);
216                 cout<<root->data<<" ";
217     }
218 }
219 
220 template <typename T>
221 void BiTree<T>::PostOrderNonRecursive(BiNode<T> * root)
222 {
223 
224     stack<BiNode<T> *> s1;
225     stack<int> s2;//s2辅助记录s1相应位置的元素的状态:s1、s2保持同步。
226             
227     while(root != NULL || !s1.empty())
228     {
229         while(root != NULL)
230         {
231             s1.push(root);
232             s2.push(1);
233             root = root->pLeft;
234         }
235         if(!s1.empty())
236         {
237             if(s2.top()==1)
238             {
239                 s2.pop();
240                 s2.push(2);
241                 root = s1.top()->pRight;
242             }
243             else
244             {
245                 root = s1.top();
246                 s1.pop();
247                 s2.pop();
248                 cout<<root->data<<" ";
249                 root = NULL;    
250             }
251         }
252         
253     }
254             
255 }
256 
257 template <typename T>
258 void BiTree<T>::PostOrder1()
259 {
260     PostOrderRecursive(root);
261     cout<<endl;
262 }
263 
264 template <typename T>
265 void BiTree<T>::PostOrder2()
266 {
267     PostOrderNonRecursive(root);
268     cout<<endl;
269 }
270 
271 template <typename T>
272 void BiTree<T>::LevelOrder(BiNode<T> * root)
273 {    
274     BiNode<T> * p;
275     queue<BiNode<T> *> q;
276     if(root == NULL) 
277         return;
278     q.push(root);
279     while(!q.empty())
280     {
281         p = q.front();
282         cout << p->data<<" ";
283         q.pop();
284         if(p->pLeft != NULL) q.push(p->pLeft);
285         if(p->pRight != NULL) q.push(p->pRight);
286     }
287 }
288 
289 template <typename T>
290 void BiTree<T>::LevelOrder()
291 {
292     LevelOrder(root);
293     cout<<endl;
294 }
295 
296 int main()
297 {
298 
299 
300     ifstream fin("BiTree.txt");// 输入文件
301     ofstream fout("out.txt");  //输出文件
302 
303     streambuf *cinbackup;
304     streambuf *coutbackup;
305 
306     cinbackup= cin.rdbuf(fin.rdbuf());  //用 rdbuf() 重新定向
307     coutbackup= cout.rdbuf(fout.rdbuf());  //用 rdbuf() 重新定向
308 
309     BiTree<char> *pbitree = new BiTree<char>;//创建一颗二叉树
310     
311     cout << "*preorder =   " << preorder << endl;
312     cout << " PreOrder1(): ";
313     pbitree->PreOrder1();
314     cout << " PreOrder2(): ";
315     pbitree->PreOrder2();
316     cout<<endl;
317     
318     cout << "*inorder =   " << inorder << endl;
319     cout << " inorder1(): ";
320     pbitree->InOrder1();
321     cout << " InOrder2(): ";
322     pbitree->InOrder2();
323     cout<<endl;
324     
325     cout << "*postorder =   " << postorder << endl;
326     cout << " PostOrder1(): ";
327     pbitree->PostOrder1();    
328     cout << " PostOrder2(): ";
329     pbitree->PostOrder2();
330     cout<<endl;
331     
332     cout << "*levelorder =  " << levelorder << endl;
333     cout << " LevelOrder(): ";
334     pbitree->LevelOrder();
335 
336     delete pbitree;
337     cin.rdbuf(cinbackup);  // 取消,恢复键盘输入
338     cout.rdbuf(coutbackup);  //取消,恢复屏幕输出
339     return 0;
340 }
View Code

 

 

 

 

 

 

 

  

  

 

 

 

     

 

 

 

 

 

  

 

  

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

标签:

原文地址:http://www.cnblogs.com/Dillonn/p/4226929.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!