二叉树非递归遍历

先序

对于任一结点p:
1)访问结点p,并将结点p入栈;
2)判断结点p的左孩子是否不空先while循环直到空,这其间要输出根节点值(因为是先序);这之后,取栈顶结点并进行出栈操作,令 p = 栈顶元素的右孩子(如果不为空循环,如果为空证明遍历完毕,会再取栈顶元素);
3)直到p为NULL并且栈为空,则遍历结束。

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        TreeNode* p = root;
        vector<int> res;
        while(p!=nullptr || !s.empty()){
            while(p != nullptr){
                res.push_back(p->val);
                s.push(p);
                p = p->left;
            }
            p = s.top();
            s.pop();
            p = p->right;
        }
        return res;
    }
};

 

中序

同前序,但因为是先输出左结点再输出根结点,所以要在每次取栈顶元素后进行输出。

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        TreeNode* p = root;
        vector<int> res;
        while(p!=nullptr || !s.empty()){
            while(p != nullptr){
                s.push(p);
                p = p->left;
            }
            p = s.top();
            res.push_back(p->val);
            s.pop();
            p = p->right;
        }
        return res;
    }
};

 

后序

因为后序的顺序是先访问左子树,再访问右子树,最后访问根节点。当用栈来存储节点,必须分清返回根节点时,是从左子树返回的,还从右子树返回的。所以,使用辅助指针r,其指向最近访问过的节点(也可以在节点中增加一个标志域,记录是否已被访问)。

取出栈顶元素之后,如果当前结点p的右结点存在且右结点不是r,证明该结点的左子树应该刚刚遍历完毕,而右子树还没有遍历,所以入栈右结点,开始遍历右子树;若p的右结点为空或者右结点就是r,则证明左子树和右子树都遍历了(空算作已遍历),此时该输出根结点了,出栈,令 r = 最近访问结点(也就是p),再将p置空(这里是为了是下次循环 while(p!=nullptr) 能直接出来以防止重复入栈)。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        TreeNode* p = root;
        TreeNode* r = nullptr;
        vector<int> res;
        while(p!=nullptr || !s.empty()){
            while(p != nullptr){
                s.push(p);
                p = p->left;
            }
            p = s.top();
            if(p->right && p->right != r){
                p = p->right;
            }else{
                res.push_back(p->val);
                s.pop();
                r = p;
                p = nullptr;
            }
        }
        return res;
    }
};

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值