代码随想录算法训练营第24天(补第12天)| 递归遍历,迭代遍历,统一迭代
前置知识
二叉树的定义:
struct BNode{
int val;
BNode* lchild;
BNode* rchild;
BNode():lchild(NULL),rchild(NULL){}
BNode(int val){
val=val;
lchild=rchild=NULL;
}
};
递归遍历
文章链接:https://programmercarl.com/二叉树的递归遍历.html#思路
题目链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/description/
https://leetcode.cn/problems/binary-tree-postorder-traversal/description/
https://leetcode.cn/problems/binary-tree-inorder-traversal/description/
前序遍历:
class Solution {
public:
void traversal(TreeNode* cur,vector<int>& res){
if(cur==NULL) 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==NULL) 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:
void traversal(TreeNode* cur,vector<int>& res){
if(cur==NULL) 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;
}
};
迭代遍历
文章链接:https://programmercarl.com/二叉树的迭代遍历.html#算法公开课
题目链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/description/
https://leetcode.cn/problems/binary-tree-inorder-traversal/description/
https://leetcode.cn/problems/binary-tree-postorder-traversal/description/
前序遍历:
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
if(root==NULL) return res;
else st.push(root);
while(!st.empty()){
TreeNode* node=st.top();
st.pop();
res.push_back(node->val);
if(node->right) st.push(node->right);
if(node->left) st.push(node->left);
}
return res;
}
};
中序遍历:由于访问顺序和处理顺序不一样,所以会稍微复杂。需要先用指针访问到树的最后一层再进行处理。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
TreeNode* cur=root;
while(cur!=NULL||!st.empty()){
//一直遍历到底部再进行处理
while(cur!=NULL){
st.push(cur);
cur=cur->left;//左
}
//可以开始处理了
if(!st.empty()){
cur=st.top(); //中
st.pop();
res.push_back(cur->val);
cur=cur->right; //右
}
}
return res;
}
};
后序遍历:
可以按照这个思路写:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if(root==NULL) return res;
else st.push(root);
while(!st.empty()){
TreeNode* node=st.top();
st.pop();
res.push_back(node->val);
if(node->left) st.push(node->left);
if(node->right) st.push(node->right);
}
reverse(res.begin(),res.end());
return res;
}
};
统一迭代
文章链接:https://programmercarl.com/二叉树的统一迭代法.html
题目链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/description/
https://leetcode.cn/problems/binary-tree-inorder-traversal/description/
https://leetcode.cn/problems/binary-tree-postorder-traversal/description/
要点:使用栈的话,无法同时解决访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况。
那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。
如何标记呢,就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。 这种方法也可以叫做标记法。
中序:
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
if(root!=NULL) st.push(root);
while(!st.empty()){
TreeNode*node=st.top();
//如果所取的头部节点不为空,就弹出
if(node!=NULL){
st.pop();
if(node->right) st.push(node->right); //右
st.push(node); //已经弹出的中间节点继续压入 中
st.push(NULL); //并添加空节点作为标识
if(node->left) st.push(node->left); //左
}
else{ //如果node不是空节点,则可取为res
st.pop();
node=st.top();
st.pop();
res.push_back(node->val);
}
}
return res;
}
};
前序:相比中序,只改变了两行的顺序
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
if(root!=NULL) st.push(root);
while(!st.empty()){
TreeNode* node=st.top();
if(node!=NULL){
st.pop();
if(node->right) st.push(node->right); //右
if(node->left) st.push(node->left); //左
st.push(node); //中
st.push(NULL); //标识
}
else{
st.pop();
node=st.top();
st.pop();
res.push_back(node->val);
}
}
return res;
}
};
后序:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
if(root!=NULL) st.push(root);
while(!st.empty()){
TreeNode* node=st.top();
if(node!=NULL){
st.push(NULL); //中
if(node->right) st.push(node->right); //右
if(node->left) st.push(node->left); //左
}
else{
st.pop();
node=st.top();
st.pop();
res.push_back(node->val);
}
}
return res;
}
};
层序遍历:
文章链接:https://programmercarl.com/0102.二叉树的层序遍历.html#_102-二叉树的层序遍历
题目链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
queue<TreeNode*> que;
int size=0;
if(root!=NULL){
que.push(root);
size++;
}
while(!que.empty()){
vector<int> curRes;
int i=0; //这里我取了i来整体记录size的最终变化。
//实际上可以用que的库函数size()来得到当前的元素个数
while(size--){
TreeNode* node=que.front();
que.pop();
if(node->left){
que.push(node->left);
i++;
}
if(node->right){
que.push(node->right);
i++;
}
curRes.push_back(node->val);
}
size=i;
res.push_back(curRes);
}
return res;
}
};