非递归实现树的三种遍历

三种非递归遍历都使用一种框架,代码如下

void traversal(TreeNode* root) {
    TreeNode*p=root;
    stack<TreeNode*>st;
    while(!st.empty() || p!=NULL){
        //将p及其左边一溜入栈
        while(p!=NULL){
            st.push(p);
            p=p->left;
        }
        //p指向栈顶元素的右孩子,即使为空
        p=st.top()->right;
        //栈顶元素出栈
        st.pop();
    }
   }

中序遍历

其核心思想在于:每次把一棵树的根节点、根节点的左孩子、左孩子的左孩子…一直到最左下角,这一条斜线上的所有节点入栈。每次取出并打印栈顶节点的值,然后对其右子树进行上述入栈操作。

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        if(!root)
            return {};
        stack<TreeNode*>st;
        while(root){
            st.push(root);
            root=root->left;
        }
        vector<int>ans;
        while(!st.empty()){
            //取出栈顶元素
            TreeNode*t=st.top();
            st.pop();
            ans.emplace_back(t->val);
            //将栈顶元素右孩子一直到其最下角的左孩子全部入栈
            TreeNode*p=t->right;
            while(p){
                st.push(p);
                p=p->left;
            }
        }
        return ans;
    }
};

前序遍历

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        TreeNode*p=root;
        vector<int>ans;
        stack<TreeNode*>st;
        while(!st.empty() || p!=NULL){
            //将p及其左边一溜先打印,再入栈
            while(p!=NULL){
                //打印
                ans.push_back(p->val);    //cout<<st.top()->val
                //入栈
                st.push(p);
                p=p->left;
            }
            //p指向栈顶元素的右孩子,即使它为空
            p=st.top()->right;
            //栈顶元素出栈
            st.pop();
        }
        return ans;
    }
};

后序遍历

后序遍历非递归的关键在于,栈顶元素何时打印,何时不打印

当栈顶元素右子树全部访问完了(pre==top()->right)或为空时,根据后序遍历的定义,此时可以打印栈顶元素;这里的pre指向上次打印的节点,由于后序遍历根最后打印,所以当pre==top()->right时,能够判断出栈顶元素的右子树所有节点已经访问完毕。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*>st;
        TreeNode*pre=NULL;
        vector<int>ans;
        TreeNode*p=root;
        while(p || !st.empty()){
            while(p){
                st.push(p);
                p=p->left;
            }
            //如果栈顶元素的右子树为空 或者 右子树存在且已经全部访问过了,则直接打印
            if(st.top()->right==NULL || st.top()->right==pre){
                ans.push_back(st.top()->val);
                pre=st.top();
                st.pop();
                p=NULL; //让下一轮直接访问栈顶元素
            }else
                p=st.top()->right;
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值