树的前中后序遍历-非递归的迭代写法

news/2024/9/23 2:34:31/

就是要我们非递归其实就是模仿递归的写法,类如递归一样遍历一棵树,但是却不是递归的写法,

防止栈溢出。

二叉树的前序遍历

先看递归代码:

void _preorderTraversal(TreeNode* root,vector<int>&v)
{if (root == NULL){return;}v.push_back(root->val);preorderTraversal(root->_left);preorderTraversal(root->_right);
}vector<int> preorderTraversal(TreeNode* root)
{vector<int> v;_preorderTraversal(root,v);return v;
}

        递归遍历访问到nullptr时,可以返回上一层结点,再去访问右子树。这里我们是在上一级栈帧中保存了直系父节点才做到,当该父节点结束以后代表他的左右结点都访问完毕,然后再返回他的上一层结点(B的左右结点访问完毕,返回到A,再去访问C)为什么能再次返回呢?因为每一层栈帧保存了一个父节点。我们的非递归就是要做到这样的情况。类似栈帧的完成方法实现,这就要使用到我们的栈了。

我们规定了遍历顺序都是先遍历左子树再遍历右子树,所以我们的前序遍历就要先访问左子树

 每到一个非空树时就要将根结点保存在栈中.然后继续访问左子树cur=cur->left

 

当访问到左树为空时就将栈顶元素拿出来并且删除栈顶元素,将拿出的二叉树根指针的右子树赋值给遍历指针

 cur遇nullptr时继续取栈顶元素并删除栈顶,右树继续赋值给cur

然后压入元素E,cur=cur->left

cur==nullptr结束循环,取栈顶元素,将元素的右树赋值给cur,并pop栈。  

cur==nullptr结束循环,取栈顶元素,将元素的右树赋值给cur,并pop栈。  

 最后访问结束后cur==nullptr,stack也是空栈。

 

访问结束,退出循环。

查看代码:

class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {stack<TreeNode*> st;vector<int> v;TreeNode*cur=root;//只有栈空并且cur==nullptr才会退出循环。while(cur ||!st.empty()){将节点访问,并且移动到左子树while(cur){//入vector就是对结点访问。v.push_back(cur->val);st.push(cur);cur=cur->left;}cur=st.top()->right;st.pop();}return v;}
};

中序遍历

中序遍历的迭代写法类似于前序迭代代码。改变访问位置即可,前序遍历都是来到一个结点先访问在去左子树,而中序就是子树访问完毕后再去访问根结点。在栈top时访问该元素即可。

看中序代码:

class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {stack<TreeNode*> st;vector<int> v;TreeNode*cur=root;while(cur ||!st.empty()){while(cur){//结点压栈,但是不访问。st.push(cur);cur=cur->left;}TreeNode* top=st.top();//取出栈顶元素后访问就是中序访问v.push_back(top->val);//访问后将top的右子树赋值给curcur=top->right;st.pop();}return v;}
};

后序遍历(重点)

画图+代码理解。

    vector<int> postorderTraversal(TreeNode* root) {stack<TreeNode*> st;vector<int> v;TreeNode*cur=root;TreeNode*prev=nullptr;while(cur ||!st.empty()){while(cur){st.push(cur);cur=cur->left;}//......

前面代码和中序遍历一样,但是我们加了一个prev指针,用来保存返回前的结点

当我们访问到cur==nullptr是取栈顶元素进行操作。

 

auto top=st.top();
if(top->right==nullptr||top->right==prev)
{v.push_back(top->val);prev=top;st.pop();
}
else
{cur=top->right;
}

 top->right==nullptr:当我们的结点的左边访问完毕后查看右边是否为空如果为空,就表示对结点数据访问。

top->right==prev:prev保存取出上一层取出栈顶的元素,我们查看他是否为这次栈顶结点的右结点,如果等于就意味着该节点的右子树访问完毕。

有点抽象吧?画个图,我也活动以下脑子。

 

 

 

 

 此刻!!大循环判断不成立退出循环

结束循环返回数据。树以后序遍历结束!!!

完整代码:

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {stack<TreeNode*> st;vector<int> v;TreeNode*cur=root;TreeNode*prev=nullptr;while(cur ||!st.empty()){while(cur){st.push(cur);cur=cur->left;}auto top=st.top();if(top->right==nullptr||top->right==prev){v.push_back(top->val);prev=top;st.pop();}else{cur=top->right;}}return v;}
};

 


http://www.ppmy.cn/news/445734.html

相关文章

python编程之变量如何自加i++

疑惑 i&#xff1b;会报错 解惑 在python编程中变量自加只有两种方式&#xff1b; ii1; i1; 没有i;

通过文献DOI下载外文文献

通过文献DOI下载外文文献 &#xff08;如果已知文献DOI&#xff0c;可直接进入第三步&#xff09; 1.可以在中国知网&#xff08;http://www.cnki.net/&#xff09;上搜索关键词得到相关文献。 2.点击文章标题&#xff0c;复制DOI。 3.进入网站SCI-HUB&#xff08;https://ww…

python 中i++、逻辑表达式

i运算符 python中没有类似i之类实现1的运算符&#xff0c;但是有i&#xff0c;i、之类的&#xff0c;他们是逻辑运算符&#xff0c;用来实现类似负负得正的功能 遇到问题没人解答&#xff1f;小编创建了一个Python学习交流QQ群&#xff1a;579817333 寻找有志同道合的小伙伴&…

使用python编写函数计算f(i),f(i)的计算公式为:f(i)=1/2+2/3+...+i/(i+1)

代码实现&#xff1a; def fn(i):if i1:return 0.5else:afloat(i)/float(i1) resafn(i-1)return resn int(input("请输入你需要计算的n项和&#xff1a;")) print("结果为:",fn(n))注意点&#xff1a; 1、该题运用递归的思想&#xff0c;最后递归…

python3的for i in range()使用注意事项!

for i in range(1&#xff0c;10)真的是让我啃了好多骨头&#xff0c;恨。 python的循环结构使用以上语法&#xff0c;range&#xff08;&#xff09;相当于是一个数组&#xff0c;默认地址从0开始&#xff0c;表示i遍历函数中的每个值。 可简写为for i in range&#xff08;1…

i++和++i的区别

1、首先&#xff0c;单独拿出来说&#xff0c;i和i的意思是一样的&#xff0c;就是i i 1。 2、如果当做运算符来说&#xff0c;就是a i 和 a i这样的形式&#xff0c;情况就不一样了。 a i的意思是&#xff0c;先把i的值赋给a&#xff0c;即a i&#xff0c;再执行i i …

终于弄明白 i = i++和 i = ++i 了

写在前面&#xff1a;前些天看完了JVM的内存结构&#xff0c;自以为自己是懂了&#xff0c;心里想想不就是分线程共享和线程私有嘛&#xff0c;然后又怎么怎么分怎么怎么的嘛… 直到遇到了这道题目。说句实话&#xff0c;曾经自己做这种运算题目&#xff0c;完全是靠脑子空想&…

iwrite复制粘贴

1&#xff0c;登录iwrite 登录iwrite 2&#xff0c;打开需要完成的作业 打开作业 3&#xff0c;按<F12>,再按<F1>,打开chrome控制台&#xff0c; 打开chrome控制台 找到Disable JavaScript前面的小方框并选中 关闭JavaScript 不要马上关闭控制台 4&#xff0c…