二叉树的层序遍历
思路:层序遍历采用队列即可。每次操作就是进行一层的遍历,将当前一层的值存进vector,并且如果当前节点的左右节点不为空,就丢进队列。
/**
* 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>> ans;
queue<TreeNode*> que;
if(root) que.push(root);
while(!que.empty()){
int siz=que.size();
vector<int> a;
while(siz--){
TreeNode* now=que.front();
que.pop();
a.push_back(now->val);
if(now->left) que.push(now->left);
if(now->right) que.push(now->right);
}
ans.push_back(a);
}
return ans;
}
};
二叉树的前序遍历
递归
思路:前序是中左右,所以先存根的值,然后dfs左右子树即可
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
void dfs(TreeNode* root){
if(!root) return ;
ans.push_back(root->val);
dfs(root->left);
dfs(root->right);
}
vector<int> preorderTraversal(TreeNode* root) {
dfs(root);
return ans;
}
};
非递归
思路:我们知道递归其实本质是栈,所以我们非递归的话,就用一个栈去模拟即可。
然后因为前序是中左右,而栈的栈顶是后加入的。
所以我们把左右结点丢入栈的时候,应该是先丢右节点,在丢左节点,这样子取出来的栈顶才是左节点。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> sta;
if(root) sta.push(root);
while(!sta.empty()){
TreeNode* now=sta.top();
sta.pop();
ans.push_back(now->val);
if(now->right) sta.push(now->right);
if(now->left) sta.push(now->left);
}
return ans;
}
};
二叉树的后序遍历
递归
思路:后序是左右中,所以先dfs左右子树,然后存根的值即可
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
void dfs(TreeNode* root){
if(!root) return ;
dfs(root->left);
dfs(root->right);
ans.push_back(root->val);
}
vector<int> postorderTraversal(TreeNode* root) {
dfs(root);
return ans;
}
};
非递归
思路:我们知道前序是中左右,后序是左右中,我们把前序的存的节点顺序反转一下那么reverse(前序)就是右左中,根据前面非递归版本的前序遍历,那么我们只要改变为先把左儿子进栈,再把右儿子进栈即可。这样出来就是中右左,整个vector反转一下就是左右中也就是后序了。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> sta;
if(root) sta.push(root);
while(!sta.empty()){
TreeNode* now=sta.top();
sta.pop();
ans.push_back(now->val);
//与前序非递归相比,这两行顺序换了换而已
if(now->left) sta.push(now->left);
if(now->right) sta.push(now->right);
}
reverse(ans.begin(),ans.end());//中右左 反转 左右中
return ans;
}
};
二叉树的中序遍历
递归
思路:中序是左中右,所以先dfs左子树,然后存根的值,最后dfs右子树
/**
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
void dfs(TreeNode* root){
if(!root) return ;
dfs(root->left);
ans.push_back(root->val);
dfs(root->right);
}
vector<int> inorderTraversal(TreeNode* root) {
dfs(root);
return ans;
}
};
非递归
思路:前面的非递归版本,我们其实一定会先存根结点的值,所以很遗憾,这里不能和前面非递归做法高度一致。那么我们知道中序是左中右,其实就是一直左子树递归。
所以本质思想就是不撞南墙不回头,也就是如果左子树不空,那么一直递归下去。
空了呢?我们取上一个结点,这个结点已经遍历过左子树了,所以开始遍历它的右子树。而因为是左中右,所以继续遍历右子树的左子树。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> sta;
while(root || !sta.empty()){
if(root){ //没撞南墙 一直遍历左子树
sta.push(root); //保存过来的结点
root=root->left;
}
else{ //撞墙了
root=sta.top();//取出上一个遍历的点
sta.pop();
ans.push_back(root->val);//
root=root->right;//开始跑右子树
}
}
return ans;
}
};