遍历方式 深度优先搜索&广度优先搜索
深度:前序遍历、中序遍历、后序遍历(中间在前or中or后,左右顺序固定)
广度:
递归分析三步法
1、确定递归函数的参数和返回值
2、确定终止条件
3、确定单层递归逻辑
前序遍历
144. 二叉树的前序遍历 - 力扣(LeetCode)
/**
* 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:
void taversal(TreeNode* cur,vector &vec){
if(cur==NULL)return;
vec.push_back(cur->val);
taversal(cur->left,vec);
taversal(cur->right,vec);
}
vector preorderTraversal(TreeNode* root) {
vector res;
taversal(root,res);
return res;
}
};
后序遍历
145. 二叉树的后序遍历 - 力扣(LeetCode)
/**
* 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:
void taversal(TreeNode* cur,vector &vec){
if(cur==NULL){return;}
taversal(cur->left,vec);
taversal(cur->right,vec);
vec.push_back(cur->val);
}
vector postorderTraversal(TreeNode* root) {
vector res;
taversal(root,res);
return res;
}
};
中序遍历
94. 二叉树的中序遍历 - 力扣(LeetCode)
/**
* 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:
void traversal(TreeNode*cur,vector &vec){
if(cur==NULL)return;
traversal(cur->left,vec);
vec.push_back(cur->val);
traversal(cur->right,vec);
}
vector inorderTraversal(TreeNode* root) {
vector res;
traversal(root,res);
return res;
}
};
思路:用栈作为中间容器,前序遍历是”中左右“根节点不为空时将根节点放入栈,使用while循环,循环条件是栈不为空,循环中首先引入一个Node节点记录栈顶的节点,然后pop掉栈里的顶部元素,将这个元素的值Node->val赋值给res结果,然后先push进栈node->right,再是node->left;因为出栈顺序是后进先出,从而实现中左右的前序遍历顺序。
前序遍历
/**
* 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 preorderTraversal(TreeNode* root) {
stack st;
vector res;
if(root==NULL)return res;
st.push(root);
while(!st.empty()){
TreeNode* Node=st.top();
st.pop();
res.push_back(Node->val);
if(Node->right!=NULL){st.push(Node->right);}
if(Node->left!=NULL){st.push(Node->left);}
}
return res;
}
};
中序遍历
中序遍历的顺序是左中右,指针元素与操作元素与前序遍历不同,所以结构不同;这里还需要引入一个遍历指针cur,先指向root,遍历中向左(cur=cur->left)直到底层,每次循环将结点存入栈中,结束时cur==NULL,此时将cur=st.top()即为底层的左元素,要将其存入res,然后pop掉;下一个top即“中节点”,处理完中结点后cur=cur->right,移动到右节点。进行下一次迭代。
/**
* 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 inorderTraversal(TreeNode* root) {
stack st;
vector res;
TreeNode* cur=root;
while(cur!=NULL||!st.empty()){
if(cur!=NULL){
st.push(cur);
cur=cur->left;
}
else{
cur=st.top();
st.pop();
res.push_back(cur->val);
cur=cur->right;
}
}
return res;
}
};
后序遍历
/**
* 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 postorderTraversal(TreeNode* root) {
stack st;
vector res;
if(root==NULL){return res;}
st.push(root);
while(!st.empty()){
TreeNode* tmp=st.top();
st.pop();
res.push_back(tmp->val);
if(tmp->left){st.push(tmp->left);}
if(tmp->right){st.push(tmp->right);}
}
reverse(res.begin(),res.end());
return res;
}
};
前序遍历
class Solution {
public:
vector inorderTraversal(TreeNode* root) {
vector result;
stack st;
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();
result.push_back(node->val); // 加入到结果集
}
}
return result;
}
};
中序遍历
class Solution {
public:
vector inorderTraversal(TreeNode* root) {
vector result;
stack st;
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 { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.top(); // 重新取出栈中元素
st.pop();
result.push_back(node->val); // 加入到结果集
}
}
return result;
}
};
后续遍历
class Solution {
public:
vector inorderTraversal(TreeNode* root) {
vector result;
stack st;
if (root != NULL) st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != NULL) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将中右左节点添加到栈中
st.push(node); // 添加中节点
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();
result.push_back(node->val); // 加入到结果集
}
}
return result;
}
};
这个办法妙啊,在while中先pop掉之前的中间元素,再按照目标的逆序push,push完中间节点就继续加一个null标记
102. 二叉树的层序遍历 - 力扣(LeetCode)
解题思路:
用队列作为容器,首先放入root,当队列不为空时进入循环;循环中,引入size=每一层节点的数量,引入vec记录每一层的节点值,在for循环中遍历每一层的节点,在vec中记录节点值并将其非空的左右儿子加入队列;for循环后在res中记录每一层的vec。
/**
* 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> levelOrder(TreeNode* root) {
vector> res;
queue que;
if(root!=NULL)que.push(root);
while(!que.empty()){
int size=que.size();
vector vec;
for(int i=0;ival);
if(node->left){que.push(node->left);}
if(node->right){que.push(node->right);}
}
res.push_back(vec);
}
return res;
}
};
107. 二叉树的层序遍历 II - 力扣(LeetCode)
在上一题的基础上,输出前反转一下res。
/**
* 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> levelOrderBottom(TreeNode* root) {
vector> res;
queue que;
if(root!=NULL)que.push(root);
while(!que.empty()){
int size=que.size();
vector vec;
for(int i=0;ival);
if(node->left){que.push(node->left);}
if(node->right){que.push(node->right);}
}
res.push_back(vec);
}
reverse(res.begin(),res.end());//只需要反转一下最后的输出
return res;
}
};
199. 二叉树的右视图 - 力扣(LeetCode)
/**
* 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 rightSideView(TreeNode* root) {
vector res;
queue que;
if(root!=NULL)que.push(root);
while(!que.empty()){
int size=que.size();
for(int i=0;ival);}//只需要将每一层的最后一个元素记录
if(node->left){que.push(node->left);}
if(node->right){que.push(node->right);}
}
}
return res;
}
};
637. 二叉树的层平均值 - 力扣(LeetCode)
在循环中引入sum,for循环中sum+=node->val;for循环结束后用res记录均值sum/size。注意使用double res、sum
/**
* 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 averageOfLevels(TreeNode* root) {
vector res;
queue que;
if(root!=NULL)que.push(root);
while(!que.empty()){
int size=que.size();
double sum=0;
for(int i=0;ival;
if(node->left){que.push(node->left);}
if(node->right){que.push(node->right);}
}
res.push_back(sum/size);
}
return res;
}
};
429. N 叉树的层序遍历 - 力扣(LeetCode)
for循环中再套一层for循环用于遍历每个结点的孩子节点,原来是只有left和right两个儿子
/*
// Definition for a Node.
class Node {
public:
int val;
vector children;
Node() {}
Node(int _val) {
val = _val;
}
Node(int _val, vector _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public:
vector> levelOrder(Node* root) {
queue que;
if (root != NULL) que.push(root);
vector> result;
while (!que.empty()) {
int size = que.size();
vector vec;
for (int i = 0; i < size; i++) {
Node* node = que.front();
que.pop();
vec.push_back(node->val);
for (int i = 0; i < node->children.size(); i++) { // 将节点孩子加入队列
if (node->children[i]) que.push(node->children[i]);
}
}
result.push_back(vec);
}
return result;
}
};
515. 在每个树行中找最大值 - 力扣(LeetCode)
引入一个maxValue,在for循环中比较node->val与maxValue,取最大值;
maxValue=node->val>maxValue? node->val:maxValue;
for循环后将最大值记录在res中。
/**
* 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 largestValues(TreeNode* root) {
vector res;
queue que;
if(root!=NULL)que.push(root);
while(!que.empty()){
int size=que.size();
int maxValue = INT_MIN;
for(int i=0;ival>maxValue? node->val:maxValue;
if(node->left){que.push(node->left);}
if(node->right){que.push(node->right);}
}
res.push_back(maxValue);
}
return res;
}
};
116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)
for循环前引入两个指针nodePre和node,nodePre表示每一行中当前节点的左侧节点,若是开头i=0则nodePre=que.top();非开头node=que.top();
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
queue que;
if(root!=NULL)que.push(root);
while(!que.empty()){
int size=que.size();//很关键
//vector vec;
Node* nodePre;
Node* node;
for(int i=0;inext=node;
nodePre=nodePre->next;
}
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
nodePre->next=NULL;
}
return root;
}
};
117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)
和上一题答案完全一样,因为已经能够让空指针不入队,
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
104. 二叉树的最大深度 - 力扣(LeetCode)
引入深度,在for循环中 每轮depth+1;就是深度
/**
* 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:
int maxDepth(TreeNode* root) {
if (root == NULL)
return 0;
int depth = 0;
queue que;
if (root != NULL)
que.push(root);
while (!que.empty()) {
int size = que.size(); // 很关键
depth++;
for (int i = 0; i < size; i++) {
TreeNode* tmp = que.front();
que.pop();
if (tmp->left)
que.push(tmp->left);
if (tmp->right)
que.push(tmp->right);
}
}
return depth;
}
};
111. 二叉树的最小深度 - 力扣(LeetCode)
解题思路:
只有左儿子右儿子都为空时才能算最浅的底部。
/**
* 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:
int minDepth(TreeNode* root) {
if (root == NULL)
return 0;
int depth = 0;
queue que;
if (root != NULL)
que.push(root);
while (!que.empty()) {
int size = que.size(); // 很关键
depth++;
for (int i = 0; i < size; i++) {
TreeNode* tmp = que.front();
que.pop();
if (tmp->left)
que.push(tmp->left);
if (tmp->right)
que.push(tmp->right);
if (tmp->left==NULL&&tmp->right==NULL){return depth;}
}
}
return depth;
}
};