前序遍历 :
递归
就是按照中前后的顺序依次访问就好了 ;
class Solution {
public:
void traversal(TreeNode* cur , vector<int>& vec){
if(cur == NULL) return ;
vec.push_back(cur->val) ;
traversal(cur->left , vec) ;
traversal(cur->right , vec) ;
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans ;
traversal(root , ans) ;
return ans ;
}
};
迭代
前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。
为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st ;
vector<int> ans ;
// 前序 : 中左右
// 每次先处理的是中间节点,那么
// 先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。
if(root == NULL) return ans ;
st.push(root);
while(!st.empty()){
TreeNode* cur = st.top() ;
st.pop() ;
ans.push_back(cur->val);
if(cur->right) st.push(cur->right) ;
if(cur->left) st.push(cur->left) ;
}
return ans ;
}
};
中序遍历
递归
按照左中右的顺序递归即可 ;
class Solution {
public:
void transfer(TreeNode* cur , vector<int>& vec){
if(cur == nullptr) return;
transfer(cur->left,vec);
vec.push_back(cur->val);
transfer(cur->right,vec);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
transfer(root,res);
return res;
}
};
迭代
因为是左中右 ,这里需要借助cur指针来帮助迭代 ;
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur != NULL || !st.empty()) {
if (cur != NULL) { // 指针来访问节点,访问到最底层
st.push(cur); // 将访问的节点放进栈
cur = cur->left; // 左
} else {
cur = st.top(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)
st.pop();
result.push_back(cur->val); // 中
cur = cur->right; // 右
}
}
return result;
}
};
后续遍历
递归
左右中
class Solution {
public:
void transfer(TreeNode* cur,vector<int>& vec){
if(cur == nullptr) return;
transfer(cur->left,vec);
transfer(cur->right,vec);
vec.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
transfer(root,res);
return res;
}
};
迭代
左右中 , 可以先转换成中右左 , 然后最后将ans反转一下即可 ;
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> result;
if (root == NULL) return result;
st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
st.pop();
result.push_back(node->val);
if (node->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)
if (node->right) st.push(node->right); // 空节点不入栈
}
reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了
return result;
}
};
二叉树的层序遍历
以下是例题
- 102.二叉树的层序遍历(opens new window)
- 107.二叉树的层次遍历II(opens new window)
- 199.二叉树的右视图(opens new window)
- 637.二叉树的层平均值(opens new window)
- 429.N叉树的层序遍历(opens new window)
- 515.在每个树行中找最大值(opens new window)
- 116.填充每个节点的下一个右侧节点指针(opens new window)
- 117.填充每个节点的下一个右侧节点指针II(opens new window)
- 104.二叉树的最大深度(opens new window)
- 111.二叉树的最小深度
102. 二叉树的层序遍历
以102为例 :
层序遍历就是从上到下,从左往右依次访问结点 ;
这里借助queue队列这种树结构就可以实现 :
先将根节点放入队列中,然后依次队列中的所有结点,再把其左右结点放入队列中,为下一层的遍历作准备 ;
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
vector<vector<int>> ans;
if(root != nullptr) que.push(root);
while(!que.empty()){
int size = que.size();
vector<int> tmp;
for(int i=0;i<size;i++){
TreeNode* node = que.front();
que.pop();
tmp.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
ans.push_back(tmp);
}
return ans;
}
};