前置知识
二叉树的定义:
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不是空节点,则可取为resst.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;}
};