p_string

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

注:本文内容参考左老师课程

二叉树的遍历分为前、中、后序,对于递归的实现方法,这里不再赘述,本文主要介绍实现非递归的方法,其核心思想均是用栈来实现,其中着重说明后序遍历。

前序遍历:相对容易

 1 //方法1
 2 void preOrderTraversal(TreeNode *root,vector<int> &pre){
 3         stack<TreeNode *> s;
 4         TreeNode *p = root;
 5         while(!s.empty() || p != NULL){
 6             while(p != NULL){
 7                 pre.push_back(p->val);
 8                 s.push(p);
 9                 p = p->left;
10             }
11             if(!s.empty()){
12                 p = s.top();
13                 s.pop();
14                 p = p->right;
15                 
16             } 
17         }        
18     }
19     //方法2
20 void preOrderTraversal(TreeNode *root,vector<int> &pre){
21         stack<TreeNode *> s;
22         TreeNode *p = root;
23         s.push(p);
24         while(!s.empty()){
25             p = s.top();
26             s.pop();
27             pre.push_back(p->val);
28             if(p->right)
29                 s.push(p->right);
30             if(p->left)
31                 s.push(p->left);
32         }        
33     }

中序遍历:

 1     void inOrderTraversal(TreeNode *root,vector<int> &in){
 2         stack<TreeNode *> s;
 3         TreeNode *p = root;
 4         while(!s.empty() || p != NULL){
 5             while(p != NULL){
 6                 s.push(p);
 7                 p = p->left;
 8             }            
 9             p = s.top();
10             in.push_back(p->val);
11             s.pop();
12             p = p->right;            
13         }
14     }

后序遍历:

方法1:使用两个栈实现(把先序访问的顺序用第二个栈存起来,然后再出栈就成了)

具体过程如下:

1.申请两个栈,记为s1,s2,然后将头节点压入s1中

2.从s1中弹出栈顶节点,记为cur,然后先把cur的左孩子压入s1中,然后把cur的右孩子压入s1中

3.在整个过程中,每一个从s1中弹出的节点都放入第二个栈s2中。

4.不断重复步骤2和步骤3,直到s1为空,过程停止。

5.从s2中依次弹出节点并打印,打印的顺序就是后序遍历的顺序了。

代码如下:

 1     void postOrderTraversal(TreeNode *root,vector<int> &post){
 2         stack<TreeNode *> s1;
 3         stack<TreeNode *> s2;
 4         TreeNode *p = root;
 5         s1.push(p);
 6         while(!s1.empty()){
 7             p = s1.top();
 8             s1.pop();
 9             s2.push(p);
10             if(p->left)
11                 s1.push(p->left);
12             if(p->right)
13                 s1.push(p->right);
14         }
15         while(!s2.empty()){
16             post.push_back(s2.top()->val);
17             s2.pop();
18         }
19     }

方法二:用一个栈来实现

具体过程如下:

  1. 申请一个栈,记为s,将头节点压入s,同时设置两个变量cur和pre,在整个遍历过程中,cur代表当前s的栈顶节点,pre代表上一次访问的结点,初始时cur为NULL,pre为头节点
  2. 每次令cur等于当前s的栈顶节点,但不从栈中弹出节点,此时分以下三种情况:
    1. 如果cur的左孩子不为空,并且pre不等于cur的左孩子,也不等于cur的右孩子(代表左孩子存在,且左右孩子都没有访问过),则把cur的左孩子压入栈s中。
    2. 如果情况1不成立,并且cur的右孩子不为空,并且pre不等于cur的右孩子(代表其左孩子为空或者其已经访问过,但其右孩子没有访问过),则把cur的右孩子压入栈s中。
    3. 如果情况1和情况2都不成立,那么从s中弹出cur并打印,然后令pre等于cur。
  3. 一直重复步骤2,直到s为空,过程停止。

 

 1     void postOrderTraversal(TreeNode *root,vector<int> &post){
 2         stack<TreeNode *> s;
 3         TreeNode *cur = NULL;
 4         TreeNode *pre = root;  //注意这里的值
 5         s.push(root);
 6         while(!s.empty()){
 7             cur = s.top();
 8             if(cur->left && pre != cur->left && pre != cur->right)  
 9                 s.push(cur->left);
10             else if(cur->right && pre != cur->right)
11                 s.push(cur->right);
12             else{
13                 s.pop();
14                 post.push_back(cur->val);
15                 pre = cur;
16             }
17         }
18     }

 

posted on 2016-09-02 15:47  p_string  阅读(605)  评论(0编辑  收藏  举报