二叉树非递归遍历--迭代

无论是何种遍历都抓住遍历的特征


先、中、后,三种遍历方式,都是深度优先搜索,差别仅在于访问根节点的顺序。

深度优先搜索的特点:

1、使用栈。

2、存在可访问节点时,向下延伸。

3、无可访问节点时,回退至上级可访问节点。


二叉树先、中、后遍历中DFS思想的体现:

1、使用栈。

2、左子树存在,向左子树迭代。

3、左子树不存在,移向右子树,回2。


1、先序

特征:一直向左,对访问的节点进行入栈,直到左边没有,回退,向右一步,再回到一直向左。

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode *root) {
        stack<TreeNode *> pStack;
        while (root || !pStack.empty()) {
            while (root) {
                result.push_back(root->val);
                pStack.push(root);
                root = root->left;
            }
            
            if (!pStack.empty()) { // 这里栈不会为空,所以可以去掉
                root = pStack.top();
                pStack.pop();
                root = root->right;
            }
        }
        return result;
    }
private:
    vector<int> result;
};



2、中序

特征:一直向左,不访问,入栈,回退访问,向右,再一直向左

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode *root) {
        stack<TreeNode *> pStack;
        while (root || !pStack.empty()) {
            while (root) {
                pStack.push(root);
                root = root->left;
            }
            
            if (!pStack.empty()) {
                root = pStack.top();
                pStack.pop();
                result.push_back(root->val);
                root = root->right;
            }
        }
        return result;
    }
private:
    vector<int> result;
};



3、后序

特征:叶节点直接访问;非叶节点,子树必须已访问,上一个被访问的必然是子节点

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        if (root == NULL) {
            return result;
        }
        stack<TreeNode *> s;
        TreeNode *pre = NULL;
        s.push(root);
        while (!s.empty()) {
            root = s.top();
            if (root->left == NULL && root->right == NULL) {
                result.push_back(root->val);
                pre = root;
                s.pop();
            } else if (root->right != NULL && pre == root->right) {
                result.push_back(root->val);
                pre = root;
                s.pop();
            } else if (root->left != NULL && pre == root->left) {
                result.push_back(root->val);
                pre = root;
                s.pop();
            } else {
                if (root->right && pre != root->right) {
                    s.push(root->right);
                }
                if (root->left && pre != root->left) {
                    s.push(root->left);
                }
            }
        }
        return result;
    }
    
private:
    vector<int> result;
};


考虑到节点如果有左子树,则必然先背访问,那么需要考虑的是右子树如果存在,有没有被访问呢?

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        if (root == NULL) {
            return result;
        }
        stack<TreeNode *> s;
        TreeNode *pre = NULL;
        TreeNode *cur = root;
        while (cur || !s.empty()) {
            while (cur) {
                s.push(cur);
                cur = cur->left;
            } // 一直向左子树方向探索
            cur = s.top();
            if (cur->right == NULL || pre == cur->right) {
                result.push_back(cur->val);
                pre = cur;
                s.pop();
                cur = NULL;
            } else {
                cur = cur->right;
            }
        }
        return result;
    }
    
private:
    vector<int> result;
};


优化


迭代条件是
1、节点不空,此时栈可能为空,进入迭代会将节点入栈;
2、或者栈不空
因此在任何遍历出栈的时候,都可以保证栈是不空的,在出栈前也就没有必要判断栈是否为空。

优化的先序

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode *root) {
        stack<TreeNode *> s;
        TreeNode *cur = root;
        while (cur || !s.empty()) {
            while (cur) {
                re.push_back(cur->val);
                s.push(cur);
                cur = cur->left;
            }
            cur = s.top();
            cur = cur->right;
            s.pop();
        }
        return re;
    }

private:
    vector<int> re;
};


优化的中序

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode *root) {
        stack<TreeNode *> s;
        while (root || !s.empty()) {
            while (root) {
                s.push(root);
                root = root->left;
            }
            
            root = s.top();
            s.pop();
            re.push_back(root->val);
            root = root->right;
        }
        return re;
    }
private:
    vector<int> re;
};

优化的后序

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        stack<TreeNode *> s;
        TreeNode *pre = NULL, *cur = root;
        while (cur || !s.empty()) {
            while (cur) {
                s.push(cur);
                cur = cur->left;
            }
            cur = s.top();
            if (cur->right && pre != cur->right) {
                cur = cur->right;
            } else {
                re.push_back(cur->val);
                pre = cur;
                s.pop();
                cur = NULL;
            }
        }
        return re;
    }
    
private:
    vector<int> re;
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值