二叉树的前序、中序、后序非递归遍历

二叉树的数据结构如下:

typedef struct TreeNode  
{  
    int val;  
    TreeNode* left;  //左孩子  
    TreeNode* right;  //右孩子  
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};  

对于前序遍历,遍历访问节点处理规则如下:优先访问根结点,然后再分别访问左孩子和右孩子。

即对任一节点P,将其看作根节点,先访问节点P的值,再将其入栈;随后按同样规则访问其左子树,左子树访问完成后再访问右子树。

具体处理:

步骤1.访问结点P,并将结点P入栈

步骤2.判断结点P的左子节点是否为空,若为空,则取栈顶节点并进行出栈操作,并将栈顶结点的右子节点置为当前的结点P,循环至步骤1;若不为空,则将P的左子节点置为当前的结点P,再循环步骤2

步骤3.直到P为NULL并且栈为空,则遍历结束

void preorderTraversal(TreeNode *root) {
        if (root == NULL) return;
        stack<TreeNode *> s;
        TreeNode *p = root;
        while (p || !s.empty()) {
            while (p) {
                s.push(p);
                cout << p->val;
                p = p->left;
            }
            if (!s.empty()) {
                p = s.top();
                s.pop();
                p = p->right;
            }
        }
        return;
    }

对于中序遍历,遍历访问节点处理规则如下:优先访问左子节点,然后再分别访问根节点和右子节点。

具体处理:

对任一节点P

步骤1.若P左子节点不为空,则将P入栈并将P的左子节点置为当前的P,并返回步骤1;若P的左子节点为NULL,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右子节点,并返回步骤1

步骤2.直到P为NULL并且栈为空,则遍历结束

void inorderTraversal(TreeNode* root) {
        if (!root) return;
        TreeNode *p = root;
        stack<TreeNode *> s;
        while (p || !s.empty()) {
            while (p) {
                s.push(p);
                p = p->left;
            }
            if (!s.empty()) {
                p = s.top();
                cout << p->val;
                s.pop();
                if (p->right) {
                    p = p->right;
                }
                else {
                    p = NULL;
                }
            }
        }
        return;
    }

对于后序遍历,遍历访问节点处理规则如下:优先访问左子节点,然后再访问右子节点,最后访问根节点。

具体处理:

思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左子节点的结点,此时该结点(没有左子节点的结点)出现在栈顶,但是此时不能将其出栈并访问, 因此其右子节点还为被访问,一个根节点被访问的前提是:无右子树或右子树已被访问过。

所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右子节点时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就 保证了正确的访问顺序。

因此,考虑记录当前节点以及上次访问的节点的位置,当 (1)上次访问节点是当前节点的右子节点 或者 (2)当前节点无右子节点并且上次访问节点是当前节点的左子节点 时,即可访问当前节点

void postorderTraversal(TreeNode* root) {
        if (!root) return;
        stack<TreeNode *> s;
        TreeNode *pCurrent, *pLastVisit;
        pCurrent = root;
        while (pCurrent || !s.empty()) {
            while (pCurrent) {
                s.push(pCurrent);
                pCurrent = pCurrent->left;
            }
            if (!s.empty()) {
                pCurrent = s.top();
                s.pop();
                if (!pCurrent->right || pCurrent->right == pLastVisit) {
                    cout << pCurrent->val;
                    pLastVisit = pCurrent;
                    pCurrent = NULL;
                }
                else {
                    s.push(pCurrent);
                    pCurrent = pCurrent->right;
                }
            }
        }
        return;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值