递归遍历 (必须掌握) 深度优先
递归三部曲:(牢记)
-
确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
-
确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
-
确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程
递归三部曲:
void traversal(TreeNode *cur,vector<int>& res){
if(cur == nullptr) return;
res.push_back(cur->val);
traversal(cur->left,res);
traversal(cur->right,res);
}
前序:
class Solution {
public:
void traversal(TreeNode *cur,vector<int>& res){
if(cur == nullptr) return;
res.push_back(cur->val);
traversal(cur->left,res);
traversal(cur->right,res);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
traversal(root,res);
return res;
}
};
中序:
class Solution {
public:
void traversal(TreeNode *cur,vector<int>&res){
if(cur==nullptr) return ;
traversal(cur->left,res);
res.push_back(cur->val);
traversal(cur->right,res);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
traversal(root,res);
return res;
}
};
后序:
class Solution {
public:
void traversal(TreeNode *cur,vector<int>&res){
if(cur==nullptr) return ;
traversal(cur->left,res);
traversal(cur->right,res);
res.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
traversal(root,res);
return res;
}
};
迭代遍历(多次复习,不如递归简单)
前序:在加入栈时,左右分支的加入情况需要考虑清楚,因为中左右,所以需要先将中弹出,然后先加入右分支,再加入左分支。(栈是先进后出)
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> sta;
vector<int> res;
if(root==nullptr) return res;
sta.push(root);
while(!sta.empty()){
TreeNode *node=sta.top();
sta.pop();
res.push_back(node->val);
if(node->right) sta.push(node->right);
if(node->left) sta.push(node->left) ;
}
return res;
}
};
后序和前序很类似。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> sta;
vector<int> res;
if(root==nullptr) return res;
sta.push(root);
while(!sta.empty()){
TreeNode *node=sta.top();
sta.pop();
res.push_back(node->val);
if(node->left) sta.push(node->left);
if(node->right) sta.push(node->right);
}
reverse(res.begin(),res.end());
return res;
}
};
中序麻烦很多。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
TreeNode *cur=root;
while(cur!=nullptr||!st.empty()){
if(cur!=nullptr){
st.push(cur);
cur=cur->left; //左
}
else{
cur=st.top();
st.pop();
res.push_back(cur->val); //中
cur=cur->right; //右
}
}
return res;
}
};
层序遍历 广度优先 很重要 很重要 很重要
细节:我们要保存队列(二叉树中每行节点的个数)的大小,因为其大小一直在变。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
queue<TreeNode*> que;
if(root!=nullptr) que.push(root);
while(!que.empty()){
vector<int> temp;
int size=que.size();
for(int i=0;i<size;i++){
TreeNode* node=que.front();
temp.push_back(node->val);
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
res.push_back(temp);
}
return res;
}
};
统一迭代法后面再学,上面的方法一定要掌握。
这个基础很重要,很重要,很重要!!!