標題
1 迭代法
迭代法比遞歸法稍微複雜一點,但無非就是藉助棧或隊列
來實現二叉樹的遍歷
1.1 前序遍歷(Leetcode 144)
- 前序遍歷: 當棧不爲空或者root不爲空節點時,
先遍歷、訪問、壓棧左節點
,當左節點不存在時
,出棧訪問右節點
/**
* Definition for a binary tree node.
* 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) {
vector<int> res;
stack<TreeNode*> s;
TreeNode* temp = root;
// 當棧不爲空或者root不爲空節點時
while(!s.empty() || temp){
//`先遍歷、訪問、壓棧左節點`
while(temp){
s.push(temp);
res.push_back(temp->val);
temp = temp->left;
}
//當訪問節點不存在左子樹時,退棧對右子樹進行訪問
temp = s.top();
s.pop();
temp = temp->right;
}
return res;
}
};
1.2 中序遍歷(Leetcode 94)
- 與前序遍歷類似,當棧不爲空或者root不爲空節點時,先
遍歷、壓棧左節點
,當左節點不存在時
,出棧先訪問棧頂節點
,然後訪問右節點
/**
* Definition for a binary tree node.
* 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) {
vector<int> res;
stack<TreeNode*> s;
TreeNode* temp = root;
//當棧不爲空或則根節點不爲空節點時
while(!s.empty() || temp){
//先`遍歷、壓棧左節點`
while(temp){
s.push(temp);
temp = temp->left;
}
//當`左節點不存在時`,出棧`先訪問棧頂節點`,`然後訪問右節點`
temp = s.top();
s.pop();
res.push_back(temp->val);
temp = temp->right;
}
return res;
}
};
1.3 後序遍歷(Leetcode 145)
- 與前序遍歷類似,只不過前序遍歷先遍歷、訪問、壓棧左節點,當左節點不存在時,出棧訪問右節點
- 而後序遍歷當棧不爲空或者root不爲空節點時,
先遍歷、訪問、壓棧右節點
,當右節點不存在
時,出棧訪問左節點
,最後**翻轉數組
**
/**
* Definition for a binary tree node.
* 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) {
vector<int> res;
stack<TreeNode*> s;
TreeNode* tmp = root;
while(!s.empty() || tmp){
//先遍歷、訪問、壓棧右節點
while(tmp){
res.push_back(tmp->val);
s.push(tmp);
tmp = tmp->right;
}
//當右節點不存在時,出棧訪問左節點
tmp = s.top();
s.pop();
tmp = tmp->left;
}
//最後翻轉數組
reverse(res.begin(), res.end());
return res;
}
};
1.4 層序遍歷(Leetcode 102)
- 使用
隊列
,按每一層從左到右的節點出現順序
來存儲節點
- 求出每一層隊列的長度,
每訪問隊列的一個頭節點
,就把該節點出列
- 並
判斷是否該節點有左子節點或右子節點
,如果有,則加入到隊列尾
,爲訪問下一層做準備
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
if(!root)
return res;
// 使用隊列,按每一層從左到右的節點出現順序來存儲節點
queue<TreeNode*> q;
q.push(root);
// 當隊列不爲空時
while(!q.empty()){
// 求出每一層隊列的長度,
int qLen = q.size();
vector<int> tmp;
for(int i=0; i<qLen; ++i){
// 每訪問隊列的一個頭節點,就把該節點出列
TreeNode* t = q.front();
q.pop();
tmp.push_back(t->val);
// 並判斷是否該節點有左子節點或右子節點,如果有,則加入到隊列尾,爲訪問下一層做準備
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
}
res.push_back(tmp);
}
return res;
}
};
2 遞歸法
代碼比較簡短,思路邏輯也很清晰。就是建立一個輔助函數,以實現遞歸。
2.1 前序遍歷(Leetcode 144)
/**
* Definition for a binary tree node.
* 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) {
vector<int> res;
helper(root, res);
return res;
}
void helper(TreeNode* root, vector<int> &res){
if(root){
res.push_back(root->val);
helper(root->left, res);
helper(root->right, res);
}
else return ;
}
};
2.2 中序遍歷(Leetcode 94)
/**
* Definition for a binary tree node.
* 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) {
vector<int> res;
helper(root, res);
return res;
}
void helper(TreeNode* root, vector<int> &res){
if(root){
helper(root->left, res);
res.push_back(root->val);
helper(root->right, res);
}
else return ;
}
};
2.3 後序遍歷(Leetcode 145)
/**
* Definition for a binary tree node.
* 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) {
vector<int> res;
helper(root, res);
return res;
}
void helper(TreeNode* root, vector<int> &res){
if(root){
helper(root->left, res);
helper(root->right, res);
res.push_back(root->val);
}
else return ;
}
};
2.4 層序遍歷(Leetcode 102)
要點有幾個:
- 利用
depth
變量記錄當前在第幾層(從0開始),進入下層時depth + 1
; - 如果
depth >= vector.size()
說明這一層還沒來過
,這是第一次來,所以得擴容
咯; - 因爲是前序遍歷,中-左-右,對於每一層來說,左邊的肯定比右邊先被遍歷到,實際上前序和中序結果都是一樣的。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
helper(root, 0, res);
return res;
}
void helper(TreeNode *root, int depth, vector<vector<int>> &ans){
if (!root) return ;
if (depth >= ans.size())
ans.push_back(vector<int> {});
ans[depth].push_back(root->val);
helper(root->left, depth + 1, ans);
helper(root->right, depth + 1, ans);
}
};