二叉树的前序,中序,后序遍历

1. 二叉树中很多的操作都可以从对二叉树的遍历入手,在遍历的基础上对树中节点进行相关的操作或做相关的信息统计。本文主要讨论二叉树的三种遍历算法。

2. 定义二叉树的结构体如下:

1 struct Node
2 {
3     int m_data;
4     Node* m_lChild;
5     Node* m_rChild;
6     Node(int data=0,Node* lChild=NULL,Node* rChild=NULL)
7         :m_data(data),m_lChild(lChild),m_rChild(rChild){}
8 };

3. 递归遍历代码很容易写,如下:

 1 //递归前序遍历
 2 void PreOrderTra(Node* pRoot)
 3 {
 4     if (pRoot)
 5     {
 6         cout<<pRoot->m_data<<"  ";
 7         PreOrderTra(pRoot->m_lChild);
 8         PreOrderTra(pRoot->m_rChild);
 9     }
10 }
11 
12 //递归中序遍历
13 void InOrderTra(Node* pRoot)
14 {
15     if (pRoot)
16     {
17         InOrderTra(pRoot->m_lChild);
18         cout<<pRoot->m_data<<"  ";
19         InOrderTra(pRoot->m_rChild);
20     }
21 }
22 
23 //递归后序遍历
24 void PostOrderTra(Node* pRoot)
25 {
26     if (pRoot)
27     {
28         PostOrderTra(pRoot->m_lChild);
29         PostOrderTra(pRoot->m_rChild);
30         cout<<pRoot->m_data<<"  ";
31     }
32 }

 

4. 递归算法代码简洁,容易理解。但是递归自身存在效率问题及栈溢出问题。下面分别给出三种算法的非递归模式。

5. 前序遍历的非递归算法。这是三种遍历算法中最容易写的一个算法,代码如下:

 1 //非递归前序遍历算法
 2 void NRPreOrderTra(Node* pRoot)
 3 {
 4     if (!pRoot)
 5     {
 6         return ;
 7     }
 8     stack<Node*> s;
 9     s.push(pRoot);
10     while (!s.empty())
11     {
12         Node* tmp=s.top();
13         s.pop();
14         cout<<tmp->m_data<<"  ";
15         if (tmp->m_rChild)
16         {
17             s.push(tmp->m_rChild);
18         }
19         if (tmp->m_lChild)
20         {
21             s.push(tmp->m_lChild);
22         }
23     }
24 }

分析:定义一个栈stack s模拟递归中的栈,每次先访问根节点,然后将右子节点压栈,最后将左子节点压栈。这样出栈时左子节点先出栈,右子节点后出栈。循环结束的条件就是栈为空,即所有节点都已经访问过。

6. 中序遍历的非递归算法。方法一:需要修改树节点的数据结构,在结构中加入visited标志位。中序遍历的过程:第一次访节点的时候,需要将节点的左子节点压栈,并将当前节点访问标志位置为true,第二次访问节点时,说明节点左子树已经访问完毕,此时打印节点信息,并将节点弹出栈,然后将节点的右子树压栈。代码如下:

 1 struct Node
 2 {
 3     int m_data;
 4     Node* m_lChild;
 5     Node* m_rChild;
 6     bool visited;
 7     Node(int data=0,Node* lChild=NULL,Node* rChild=NULL)
 8         :m_data(data),m_lChild(lChild),m_rChild(rChild),visited(false){}
 9 };
10 
11 void NRInOrderTra(Node* pRoot)
12 {
13     if (!pRoot)
14     {
15         return ;
16     }
17     stack<Node*> s;
18     s.push(pRoot);
19     while (!s.empty())
20     {
21         Node* tmp=s.top();
22         if (tmp!=NULL)
23         {
24             if (!tmp->visited)
25             {
26                 s.push(tmp->m_lChild);
27             }
28             else
29             {
30                 s.pop();
31                 cout<<tmp->m_data<<"  ";
32                 s.push(tmp->m_rChild);
33             }
34         }
35         else
36         {
37             s.pop();
38             if (!s.empty())
39             {
40                 s.top()->visited=true;
41             }
42         }
43     }
44 }

分析:在上述代码中为了减少对节点左右子树是否为空的判断,将NULL空子树也压入栈,容易想到栈中绝不会出现相邻元素都是NULL的情况。在弹栈的时候对是否为NULL进行判断,如果为NULL,则直接出栈,并将栈顶元素的visited位置为true。这种方法比较简单,但是缺点是需要需改原有的数据结构。

方法二:不需要修改数据结构。使用一个current指针,最初current指针值为root。访问它的左节点,并将左节点压栈,直到到达NULL节点,说明已经到达叶子节点。然后弹出栈顶元素,将current置为栈顶元素,输出current的值,然后将current置为current的右子节点。如此反复进行。

 1 void NRInOrderTra(Node* pRoot)
 2 {
 3     if (!pRoot)
 4     {
 5         return ;
 6     }
 7     stack<Node*> s;
 8     Node* current=pRoot;
 9     while (!s.empty() || current)
10     {
11         if(current)
12         {
13             s.push(current);
14             current=current->m_lChild;
15         }
16         else
17         {
18             current=s.top();
19             s.pop();
20             cout<<current->m_data<<"  ";
21             current=current->m_rChild;
22         }
23     }
24 }

注意:上述算法关键是current每一步的赋值问题。

7. 非递归后序遍历。方法一:通过数据结构中添加visited标志位来实现。主要思想:第一次访问节点时,将左节点压入堆栈;第二次访问节点时,说明左节点已经访问完,将右节点压入堆栈;第三次访问节点时,说明左右节点都已经访问完成,输出这个节点的值,从栈中弹出这个节点。算法终止条件:栈为空。

方法二:由于没有指向父节点的指针,所以只能使用栈来实现。我们使用一个prev指针来记录上一次访问的节点,curr为栈顶节点即当前访问的节点。

如果pre是curr的parent,那么向下遍历树。这种情况下就访问curr的左节点,如果左节点不为空,将左节点压栈;else如果右节点不为空,将右节点压栈。如果左右节点都为空,打印curr的值,将它弹出栈。

如果pre是curr的左节点,我们正在从左子树向上访问树。此时如果curr的右子树不为空,那么将右子节点压栈;如果右子树为空,那么输出curr的值,并将curr弹出栈。

如果pre是curr的右节点,那么输出curr的值,并将curr弹出栈。

代码如下:

 1 void NRPostOrderTra(Node* pRoot)
 2 {
 3     if (!pRoot)
 4     {
 5         return ;
 6     }
 7     stack<Node*> s;
 8     s.push(pRoot);
 9     Node* prev=NULL;
10     while (!s.empty())
11     {
12         Node* curr=s.top();
13         //从上向下访问树
14         if (!prev || prev->m_lChild==curr || prev->m_rChild==curr)
15         {
16             if (curr->m_lChild)
17             {
18                 s.push(curr->m_lChild);
19             }
20             else if (curr->m_rChild)
21             {
22                 s.push(curr->m_rChild);
23             }
24             else
25             {
26                 cout<<curr->m_data<<"  ";
27                 s.pop();
28             }
29         }
30         //从左子树向上访问树
31         else if (curr->m_lChild==prev)
32         {
33             if (curr->m_rChild)
34             {
35                 s.push(curr->m_rChild);
36             }
37             else
38             {
39                 cout<<curr->m_data<<"  ";
40                 s.pop();
41             }
42         }
43         //从右子树向上访问树
44         else if (curr->m_rChild==prev)
45         {
46             cout<<curr->m_data<<"  ";
47             s.pop();
48         }
49         prev=curr;
50     }
51 }

上述代码虽然逻辑上很清晰,但是存在很多冗余代码,即cout<<curr->m_data<<"  "; s.pop();出现多次,代码可以作如下精简:

 1 void NRPostOrderTra(Node* pRoot)
 2 {
 3     if (!pRoot)
 4     {
 5         return ;
 6     }
 7     stack<Node*> s;
 8     s.push(pRoot);
 9     Node* prev=NULL;
10     while (!s.empty())
11     {
12         Node* curr=s.top();
13         //从上向下访问树
14         if (!prev || prev->m_lChild==curr || prev->m_rChild==curr)
15         {
16             if (curr->m_lChild)
17             {
18                 s.push(curr->m_lChild);
19             }
20             else if (curr->m_rChild)
21             {
22                 s.push(curr->m_rChild);
23             }
24         }
25         //从左子树向上访问树
26         else if (curr->m_lChild==prev)
27         {
28             if (curr->m_rChild)
29             {
30                 s.push(curr->m_rChild);
31             }
32         }
33         //从右子树向上访问树
34         else
35         {
36             cout<<curr->m_data<<"  ";
37             s.pop();
38         }
39         prev=curr;
40     }
41 }

即将三种输出情况全放到最后一个else循环中。

方法三:这种方法比较新颖。需要用到两个stack。第一个的压栈顺序时:根--》左节点--》右节点。其出栈方式是:根先出栈,然后是右节点--》左节点。第二个栈的压栈顺序是第一个栈的出栈顺序:根--》右节点--》左节点。那么第二个栈的出栈顺序为:左节点--》右节点--》根。这正是后序遍历的顺序。代码如下:

 1 void NRPostOrderTra(Node* pRoot)
 2 {
 3     if (!pRoot)
 4     {
 5         return ;
 6     }
 7     stack<Node*> s;
 8     stack<Node*> output;
 9     s.push(pRoot);
10     while (!s.empty())
11     {
12         Node* curr=s.top();
13         output.push(curr);
14         s.pop();
15         if (curr->m_lChild)
16         {
17             s.push(curr->m_lChild);
18         }
19         if (curr->m_rChild)
20         {
21             s.push(curr->m_rChild);
22         }
23     }
24     while (!output.empty())
25     {
26         cout<<output.top()->m_data<<"  ";
27         output.pop();
28     }
29 }

复杂度分析:方法二和方法三时间复杂度都是O(n)。方法二的空间复杂度是O(h),h为树的高度。方法三需要两个栈,空间复杂度为O(n)。

8. 附上可执行所有代码:

View Code
  1 #include <iostream>
  2 #include <cassert>
  3 #include <string>
  4 #include <fstream>
  5 #include <vector>
  6 #include <queue>
  7 #include <stack>
  8 using namespace std;
  9 
 10 struct Node
 11 {
 12     int m_data;
 13     Node* m_lChild;
 14     Node* m_rChild;
 15     Node(int data=0,Node* lChild=NULL,Node* rChild=NULL)
 16         :m_data(data),m_lChild(lChild),m_rChild(rChild){}
 17 };
 18 
 19 //struct Node
 20 //{
 21 //    int m_data;
 22 //    Node* m_lChild;
 23 //    Node* m_rChild;
 24 //    bool visited;
 25 //    Node(int data=0,Node* lChild=NULL,Node* rChild=NULL)
 26 //        :m_data(data),m_lChild(lChild),m_rChild(rChild),visited(false){}
 27 //};
 28 //
 29 //void NRInOrderTra(Node* pRoot)
 30 //{
 31 //    if (!pRoot)
 32 //    {
 33 //        return ;
 34 //    }
 35 //    stack<Node*> s;
 36 //    s.push(pRoot);
 37 //    while (!s.empty())
 38 //    {
 39 //        Node* tmp=s.top();
 40 //        if (tmp!=NULL)
 41 //        {
 42 //            if (!tmp->visited)
 43 //            {
 44 //                s.push(tmp->m_lChild);
 45 //            }
 46 //            else
 47 //            {
 48 //                s.pop();
 49 //                cout<<tmp->m_data<<"  ";
 50 //                s.push(tmp->m_rChild);
 51 //            }
 52 //        }
 53 //        else
 54 //        {
 55 //            s.pop();
 56 //            if (!s.empty())
 57 //            {
 58 //                s.top()->visited=true;
 59 //            }
 60 //        }
 61 //    }
 62 //}
 63 //方法二不需要返回值来构造一棵树,传递指针的地址来改变指针的指向
 64 //这种方法可以修改为:传递指针的引用来改变指针的指向:
 65 //void CreateTree(Node* &pNode,vector<int>::iterator &begin,vector<int>::iterator end)
 66 void CreateTree(Node** pNode,vector<int>::iterator &begin,vector<int>::iterator end)
 67 {
 68     if (*begin!=-1)
 69     {
 70         *pNode=new Node(*begin);
 71         if (*pNode)
 72         {
 73             if (++begin!=end)
 74             {
 75                 CreateTree(&((*pNode)->m_lChild),begin,end);
 76             }
 77             if (++begin!=end)
 78             {
 79                 CreateTree(&((*pNode)->m_rChild),begin,end);
 80             }
 81         }
 82     }
 83 }
 84 
 85 Node* CreateTree(const char* fileName)
 86 {
 87     ifstream inFile;
 88     inFile.open(fileName);
 89     int value;
 90     vector<int> vec;
 91     while (inFile>>value)
 92     {
 93         vec.push_back(value);
 94     }
 95     if (vec.empty())
 96     {
 97         return NULL;
 98     }
 99     Node* pRoot=NULL;
100     //pRoot=CreateTree(pRoot,vec.begin(),vec.end());
101     CreateTree(&pRoot,vec.begin(),vec.end());
102     return pRoot;
103 }
104 
105 //递归前序遍历
106 void PreOrderTra(Node* pRoot)
107 {
108     if (pRoot)
109     {
110         cout<<pRoot->m_data<<"  ";
111         PreOrderTra(pRoot->m_lChild);
112         PreOrderTra(pRoot->m_rChild);
113     }
114 }
115 
116 //递归中序遍历
117 void InOrderTra(Node* pRoot)
118 {
119     if (pRoot)
120     {
121         InOrderTra(pRoot->m_lChild);
122         cout<<pRoot->m_data<<"  ";
123         InOrderTra(pRoot->m_rChild);
124     }
125 }
126 
127 //递归后序遍历
128 void PostOrderTra(Node* pRoot)
129 {
130     if (pRoot)
131     {
132         PostOrderTra(pRoot->m_lChild);
133         PostOrderTra(pRoot->m_rChild);
134         cout<<pRoot->m_data<<"  ";
135     }
136 }
137 
138 
139 void NRInOrderTra(Node* pRoot)
140 {
141     if (!pRoot)
142     {
143         return ;
144     }
145     stack<Node*> s;
146     Node* current=pRoot;
147     while (!s.empty() || current)
148     {
149         if(current)
150         {
151             s.push(current);
152             current=current->m_lChild;
153         }
154         else
155         {
156             current=s.top();
157             s.pop();
158             cout<<current->m_data<<"  ";
159             current=current->m_rChild;
160         }
161     }
162 }
163 
164 //非递归前序遍历算法
165 void NRPreOrderTra(Node* pRoot)
166 {
167     if (!pRoot)
168     {
169         return ;
170     }
171     stack<Node*> s;
172     s.push(pRoot);
173     while (!s.empty())
174     {
175         Node* tmp=s.top();
176         s.pop();
177         cout<<tmp->m_data<<"  ";
178         if (tmp->m_rChild)
179         {
180             s.push(tmp->m_rChild);
181         }
182         if (tmp->m_lChild)
183         {
184             s.push(tmp->m_lChild);
185         }
186     }
187 }
188 
189 //void NRPostOrderTra(Node* pRoot)
190 //{
191 //    if (!pRoot)
192 //    {
193 //        return ;
194 //    }
195 //    stack<Node*> s;
196 //    s.push(pRoot);
197 //    Node* prev=NULL;
198 //    while (!s.empty())
199 //    {
200 //        Node* curr=s.top();
201 //        //从上向下访问树
202 //        if (!prev || prev->m_lChild==curr || prev->m_rChild==curr)
203 //        {
204 //            if (curr->m_lChild)
205 //            {
206 //                s.push(curr->m_lChild);
207 //            }
208 //            else if (curr->m_rChild)
209 //            {
210 //                s.push(curr->m_rChild);
211 //            }
212 //            else
213 //            {
214 //                cout<<curr->m_data<<"  ";
215 //                s.pop();
216 //            }
217 //        }
218 //        //从左子树向上访问树
219 //        else if (curr->m_lChild==prev)
220 //        {
221 //            if (curr->m_rChild)
222 //            {
223 //                s.push(curr->m_rChild);
224 //            }
225 //            else
226 //            {
227 //                cout<<curr->m_data<<"  ";
228 //                s.pop();
229 //            }
230 //        }
231 //        //从右子树向上访问树
232 //        else if (curr->m_rChild==prev)
233 //        {
234 //            cout<<curr->m_data<<"  ";
235 //            s.pop();
236 //        }
237 //        prev=curr;
238 //    }
239 //}
240 
241 //void NRPostOrderTra(Node* pRoot)
242 //{
243 //    if (!pRoot)
244 //    {
245 //        return ;
246 //    }
247 //    stack<Node*> s;
248 //    s.push(pRoot);
249 //    Node* prev=NULL;
250 //    while (!s.empty())
251 //    {
252 //        Node* curr=s.top();
253 //        //从上向下访问树
254 //        if (!prev || prev->m_lChild==curr || prev->m_rChild==curr)
255 //        {
256 //            if (curr->m_lChild)
257 //            {
258 //                s.push(curr->m_lChild);
259 //            }
260 //            else if (curr->m_rChild)
261 //            {
262 //                s.push(curr->m_rChild);
263 //            }
264 //        }
265 //        //从左子树向上访问树
266 //        else if (curr->m_lChild==prev)
267 //        {
268 //            if (curr->m_rChild)
269 //            {
270 //                s.push(curr->m_rChild);
271 //            }
272 //        }
273 //        //从右子树向上访问树
274 //        else
275 //        {
276 //            cout<<curr->m_data<<"  ";
277 //            s.pop();
278 //        }
279 //        prev=curr;
280 //    }
281 //}
282 
283 //使用双栈的代码
284 void NRPostOrderTra(Node* pRoot)
285 {
286     if (!pRoot)
287     {
288         return ;
289     }
290     stack<Node*> s;
291     stack<Node*> output;
292     s.push(pRoot);
293     while (!s.empty())
294     {
295         Node* curr=s.top();
296         output.push(curr);
297         s.pop();
298         if (curr->m_lChild)
299         {
300             s.push(curr->m_lChild);
301         }
302         if (curr->m_rChild)
303         {
304             s.push(curr->m_rChild);
305         }
306     }
307     while (!output.empty())
308     {
309         cout<<output.top()->m_data<<"  ";
310         output.pop();
311     }
312 }
313 
314 //打印二叉树中某层次的节点,从左到右
315 //根节点为第0层
316 //成功返回1,失败返回0
317 int PrintNodeAtLevel(Node* root,int level)
318 {
319     if (!root || level<0)
320     {
321         return 0;
322     }
323     if (level==0)
324     {
325         cout<<root->m_data<<"  ";
326         return 1;
327     }
328     return PrintNodeAtLevel(root->m_lChild,level-1) | PrintNodeAtLevel(root->m_rChild,level-1);
329 }
330 
331 //求二叉树的深度
332 int Depth(Node* root)
333 {
334     if (!root)
335     {
336         return 0;
337     }
338     return 1+(max(Depth(root->m_lChild),Depth(root->m_rChild)));
339 }
340 
341 //利用二叉树的深度及打印二叉树的某层次的节点来
342 //层次遍历二叉树
343 void LevelTra1(Node* root)
344 {
345     if (!root)
346     {
347         return;
348     }
349     int depth=Depth(root);
350     for (int i=0;i<depth;i++)
351     {
352         PrintNodeAtLevel(root,i);
353         cout<<endl;
354     }
355 }
356 
357 //当不知道二叉树的深度时,利用PrintNodeAtLevel的返回值
358 //来结束循环
359 void LevelTra2(Node* root)
360 {
361     if (!root)
362     {
363         return;
364     }
365     int depth=Depth(root);
366     for (int i=0;;i++)
367     {
368         if (!PrintNodeAtLevel(root,i))
369         {
370             break;
371         }
372         cout<<endl;
373     }
374 }
375 
376 //非递归,利用queue记录节点信息来层次
377 //遍历二叉树。但是这种做法,怎样才能做
378 //到访问每层之后打印一个换行呢?
379 void LevelTra3(Node* root)
380 {
381     if (!root)
382     {
383         return;
384     }
385     queue<Node*> m_queue;
386     m_queue.push(root);
387     while (!m_queue.empty())
388     {
389         Node* cur=m_queue.front();
390         cout<<cur->m_data<<"  ";
391         m_queue.pop();
392         if (cur->m_lChild)
393         {
394             m_queue.push(cur->m_lChild);
395         }
396         if (cur->m_rChild)
397         {
398             m_queue.push(cur->m_rChild);
399         }
400     }
401     cout<<endl;
402 }
403 
404 //编程之美上的方法:cur和last
405 //两个下标太巧妙了!!!
406 void LevelTra4(Node* root)
407 {
408     if (!root)
409     {
410         return;
411     }
412     vector<Node*> vec;
413     vec.push_back(root);
414     int cur=0;
415     int last=1;
416     while (cur<vec.size())
417     {
418         last=vec.size();
419         while (cur<last)
420         {
421             cout<<vec[cur]->m_data<<"  ";
422             if (vec[cur]->m_lChild)
423             {
424                 vec.push_back(vec[cur]->m_lChild);
425             }
426             if (vec[cur]->m_rChild)
427             {
428                 vec.push_back(vec[cur]->m_rChild);
429             }
430             cur++;
431         }
432         cout<<endl;
433     }
434 }
435 
436 //编程之美上的扩展问题2:
437 //从下往上层次遍历,并且每一层从右向左输出
438 void ReverseLevelTra1(Node* root)
439 {
440     if (!root)
441     {
442         return;
443     }
444     vector<Node*> vec;
445     vec.push_back(root);
446     vec.push_back(NULL);
447     int cur=0;
448     int last=2;
449     while (cur<vec.size()-1)
450     {
451         last=vec.size();
452         while (cur<last)
453         {
454             if (vec[cur] && vec[cur]->m_lChild)
455             {
456                 vec.push_back(vec[cur]->m_lChild);
457             }
458             if (vec[cur] && vec[cur]->m_rChild)
459             {
460                 vec.push_back(vec[cur]->m_rChild);
461             }
462             cur++;
463         }
464         vec.push_back(NULL);
465     }
466     vec.pop_back();
467     vec.pop_back();
468     for (int i=vec.size()-1;i>=0;i--)
469     {
470         if (vec[i])
471         {
472             cout<<vec[i]->m_data<<"  ";
473         }
474         else
475         {
476             cout<<endl;
477         }
478     }
479     cout<<endl;
480 }
481 
482 
483 //编程之美上的扩展问题1:
484 //从下往上层次遍历,并且每一层从左向右输出
485 void ReverseLevelTra2(Node* root)
486 {
487     if (!root)
488     {
489         return;
490     }
491     vector<Node*> vec;
492     vec.push_back(root);
493     vec.push_back(NULL);
494     int cur=0;
495     int last=2;
496     while (cur<vec.size()-1)
497     {
498         last=vec.size();
499         while (cur<last)
500         {
501             if (vec[cur] && vec[cur]->m_rChild)
502             {
503                 vec.push_back(vec[cur]->m_rChild);
504             }
505             if (vec[cur] && vec[cur]->m_lChild)
506             {
507                 vec.push_back(vec[cur]->m_lChild);
508             }
509             cur++;
510         }
511         vec.push_back(NULL);
512     }
513     //这里需要注意最后vec中最后连个均为NULL,需要全pop出来
514     vec.pop_back();
515     vec.pop_back();
516     for (int i=vec.size()-1;i>=0;i--)
517     {
518         if (vec[i])
519         {
520             cout<<vec[i]->m_data<<"  ";
521         }
522         else
523         {
524             cout<<endl;
525         }
526     }
527     cout<<endl;
528 }
529 
530 //利用二叉树的深度及打印二叉树的某层次的节点来
531 //从低向上层次遍历二叉树
532 void ReverseLevelTra3(Node* root)
533 {
534     if (!root)
535     {
536         return;
537     }
538     int depth=Depth(root);
539     for (int i=depth-1;i>=0;i--)
540     {
541         PrintNodeAtLevel(root,i);
542         cout<<endl;
543     }
544 }
545 
546 int main()
547 {
548     char* fileName="tree.txt";
549     Node* pTree=CreateTree(fileName);
550 
551     cout<<"递归中序遍历:";
552     InOrderTra(pTree);
553     cout<<endl;
554     cout<<"非递归中序遍历:";
555     NRInOrderTra(pTree);
556     cout<<endl;
557 
558     cout<<"递归前序遍历:";
559     PreOrderTra(pTree);
560     cout<<endl;
561     cout<<"非递归前序遍历:";
562     NRPreOrderTra(pTree);
563     cout<<endl;
564 
565     cout<<"递归后序遍历:";
566     PostOrderTra(pTree);
567     cout<<endl;
568     cout<<"非递归后序遍历:";
569     NRPostOrderTra(pTree);
570     cout<<endl;
571 
572     PrintNodeAtLevel(pTree,2);
573     cout<<endl;
574     cout<<Depth(pTree)<<endl;
575     LevelTra1(pTree);
576     LevelTra2(pTree);
577     LevelTra3(pTree);
578     LevelTra4(pTree);
579     ReverseLevelTra1(pTree);
580     ReverseLevelTra2(pTree);
581     ReverseLevelTra3(pTree);
582 }

tree.txt文件内容:

1 2 4 -1 -1 5 7 -1 -1 8 -1 -1 3 -1 6 -1 -1

生成的树图见《编程之美》P257 图3-23

9. 熟悉三种遍历算法。

参考文章:

http://www.leetcode.com/2010/04/binary-search-tree-in-order-traversal.html

http://www.leetcode.com/2010/10/binary-tree-post-order-traversal.html

转载于:https://www.cnblogs.com/ZJUKasuosuo/archive/2012/08/26/2657784.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值