力扣题的链接在下面
二叉树的前,中,序用递归很简单我这里就不写了,主要来看非递归的实现
前序的非递归
思路:用栈的后进先出来控制结点,还是比较简单的
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
//用栈来存放树的结点
stack<TreeNode*> st;
//遍历的结果放在数组返回
vector<int> ret;
//用cur遍历树
TreeNode* cur = root;
//结束条件是当cur为空,并且栈里没有结点了
while(cur || !st.empty())
{
//循环每次都是去左节点当cur为空这个子树的左节点就访问完了
while(cur)
{
//前序是先记录数据再左,再右
//保存要返回的数据
ret.push_back(cur->val);
//每次访问的结点都保持,入栈
st.push(cur);
//向左树走
cur = cur->left;
}
//走到这里这里就说明了,当前子树左结点访问完了,保存这个结点,去访问它的右结点
TreeNode* top = st.top();
//保存了就可以出栈了
st.pop();
//这个结点的值已经保存了,并且这个结点的左节点已经访问过了,访问右树
cur = top->right;
}
return ret;
}
};
中序
思路: 中序跟前序的思路差不多,只是要先找到最左结点
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> ret;
TreeNode* cur = root;
while(cur || !st.empty())
{
//cur指向谁就表示开始访问它的左结点
//左路结点入栈
while(cur)
{
st.push(cur);
cur = cur->left;
}
//化为子问题去访问它的左节点
TreeNode* top = st.top();
st.pop();
//取出的结点,说明它的右结点已经访问过了
ret.push_back(top->val);
cur = top->right;
}
return ret;
}
};
后序
后序比前,中序都要难一点,比较抽象,先看波代码
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> ret;
TreeNode* cur;
TreeNode* prev;
while(cur || st.empty())
{
whlie(cur)
{
//左路结点入栈
st.push(cur);
cur = cur->left;
}
TreeNode* top = st.top();
if(top->right == nullptr ||top->right == prev)
{
st.pop();
ret.push_back(top->val);
prev = top;
}
else
{
cur = top->right;
}
}
return ret;
没有注释不好理解
思路:前面还是跟上面一样,还是先访问树的左结点,入栈,后序是先左子树,右子树,根,
情况1就是结点的right为空,这个时候就可以访问这个结点
情况2:right不为空,那么这个时候我们就需要去迭代它的右树,化为子问题,要注意的是当right不为空,我们还没有迭代它的右树,我们是不可以访问这个结点需要先去访问它的右结点,这个时候我们可以用一个前驱指针指向我们出栈的,就是上一个访问的结点,如果它的右树的根是上一个访问的那么就说明了右树访问过了,可以访问该结点了 (top->right = prev)这个判段条件,右树为空就判空,不是空,看上一个访问的是不是这个右树的根来判断是不是访问过,后序遍历是比较难的,挺抽象的不容易理解,建议画画图跟着代码