前中后序遍历(DFS)

首先我们要明确前中后序遍历的顺序:

  • 前序:中左右
  • 中序:左中右
  • 后序:左右中

前中后序遍历的递归代码和迭代代码分别有各自的框架,然后根据遍历顺序调整记录元素的位置即可。

递归

class Solution {
private:
    void postOrder(TreeNode* root, vector<int>& vec) {
        if (!root) return;
        postOrder(root->left, vec);	// 1
        postOrder(root->right, vec);// 2
        vec.push_back(root->val);		// 3
    }
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        postOrder(root, res);
        return res;
    }
};
  • 前序遍历:3->1->2
  • 中序遍历:1->3->2
  • 后序遍历:1->2->3

如前所述,三种遍历的迭代方式很简单,并且更改迭代方式只要调整记录元素的位置即可。

迭代

前序遍历

我们以前序遍历给出迭代版本的框架,核心思想就是用栈。

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> S;
        TreeNode* node = root;
        while (node || !S.empty()) {
            while (node) {
                res.push_back(node->val);			// 注意
                S.push(node);
                node = node->left;
            }
            node = S.top();		
            S.pop();
            node = node->right;	
        }
        return res;
    }
};
中序遍历

与前序遍历的差别请看代码中的 注意,调整了记录元素的位置。

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        if (!root) return {};
        vector<int> res;
        stack<TreeNode*> S;
        TreeNode* curr = root;
        while (curr || !S.empty()) {
            while (curr) {
                S.push(curr);
                curr = curr->left;
            }
            TreeNode* node = S.top();
            S.pop();
            res.push_back(node->val);			// 注意
            curr = node->right;
        }
        return res;
    }
};
后序遍历

注意到前序遍历的顺序为:中左右,而我们想要的后序遍历的顺序为:左右中。我们可以先讲前序遍历代码中访问左右子树的顺序互换,得到顺序为:中右左,再进行 reverse,得到后序:左右中。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if (!root) return {};
        vector<int> res;
        stack<TreeNode*> S;
        S.push(root);
        while (!S.empty()) {
            TreeNode* node = S.top();
            S.pop();
            res.push_back(node->val);
            if (node->left) S.push(node->left);
            if (node->right) S.push(node->right);
        }
        reverse(res.begin(), res.end());
        return res;
    }
};

层序遍历(BFS)

不需按深度划分

直接输出层序遍历序列,不需按深度划分,不同于 DFS 使用栈,这里是用队。

class Solution {
public:
    vector<int> levelOrder(TreeNode* root) {
        if (!root) return {};
        queue<TreeNode*> Q;
        // vector<vector<int>> res;
        vector<int> res;
        Q.push(root);
        while (!Q.empty()) {
            TreeNode* curr = Q.front();
            res.push_back(curr->val);
            Q.pop();
            if(curr->left) Q.push(curr->left);
            if(curr->right) Q.push(curr->right);
        }
        return res;
    }
}

需要按深度划分

注意在不需要按深度划分的版本的基础上做些改变,用 n 记录当前深度的节点的个数,然后在 for 循环中将这 n 个节点保存到一个数组中,下一层深度再用一个新数组保存,从而达到按深度划分。

注意在本题的基础上修改,可解决 LeetCode 中许多层序遍历的变种问题。

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        if (!root) return {};
        vector<vector<int>> res;
        queue<TreeNode*> Q;
        Q.push(root);
        while (!Q.empty()) {
            vector<int> vec;
            int n = Q.size();
            for (int i=0; i<n; ++i) {
                TreeNode* curr = Q.front();
                Q.pop();
                vec.push_back(curr->val);
                if (curr->left) Q.push(curr->left);
                if (curr->right) Q.push(curr->right);
            }
            res.push_back(vec);
        }
        return res;
    }
}

Ref:

https://github.com/youngyangyang04/leetcode-master/blob/master/problems/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8%BF%AD%E4%BB%A3%E9%81%8D%E5%8E%86.md

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐