p_string

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  37 随笔 :: 0 文章 :: 1 评论 :: 71327 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

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

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

前序遍历:相对容易

复制代码
 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   p_string  阅读(608)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示