深度优先遍历
给你二叉树的根节点 root
,返回它节点值的 前序 /中序 /后序 遍历。
递归
二叉树的遍历默认是先左后右
cpp
//二叉树遍历函数
void traverse(TreeNode* root){//从某一节点开始
if(root==nullptr) return;
traverse(root->left);//访问该节点的左子节点
traverse(root->right);//访问该节点的右子节点
}
不管前序、中序还是后序,二叉树的遍历顺序是一致的,该顺序和前序遍历一致。不同序的区别其实在于何时记录一个节点。
任何节点均会被访问三次
- 初次访问该节点,还未访问它的左子节点。
- 完成左子节点的访问,回到该节点,即将访问右子节点。
- 完成右子节点的访问,回到该节点,并继续向上返回
在以上三个时刻对该节点的值进行返回,就分别对应前序 /中序 /后序
cpp
vector<int> ans;
void traverse(TreeNode* root){
if(root==nullptr) return;
//前序处理时机
traverse(root->left);
//中序处理时机
traverse(root->right);
//后序处理时机
}
本题的处理为ans.push_back(root->val);
迭代
用栈实现
前序
每次while
循环都会弹出一个node
,然后让node->right
入栈,再让node->left
入栈,此时node->left
在栈顶。下一次循环会弹出node->left
,如果为nullptr
,不会有元素入栈,下一次循环会弹出node->right
,也就是中左右的遍历顺序。
cpp
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans;
stack<TreeNode*> st;
st.push(root);
TreeNode* top;
while(!st.empty()){
top = st.top();
st.pop();
if(top){
if(top->right) st.push(top->right);//右结点先入栈,后出栈
if(top->left) st.push(top->left);
ans.push_back(top->val);
}
}
return ans;
}
};
后序
cpp
//待写入
中序
cpp
//待写入
统一写法
cpp
//待写入
广度优先遍历
即层序遍历
102. 二叉树的层序遍历 - 力扣(LeetCode)
给你二叉树的根节点
root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
- 用
size
记录队列中节点个数,决定本层要弹出几次 - 每弹出一个节点,都要把左右子节点加入队列(如果存在的话)
- 当所有节点都被弹出,队列中只剩下被弹出的所有节点的子节点,也就是完整的下一层元素
size
可以区分队列内哪些节点属于同一层
cpp
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
queue<TreeNode*> q;
if(root == nullptr) return result;
q.push(root);
int size ;
TreeNode* temp;
while(!q.empty()){
size = q.size();
vector<int> ans;
for(int i = 0;i<size;i++){
temp = q.front();
q.pop();
ans.push_back(temp->val);
if(temp->left) q.push(temp->left);
if(temp->right) q.push(temp->right);
}
result.push_back(ans);
}
return result;
}
};