这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战
既然说是模版,可以解决哪些类型的题目是关键:
- 层序遍历 → 输出各种样式的结果
- 树宽度 → 横向最长,也只有层序遍历之后才知道结果
- 最短路 → 无权最短路径问题
来几个题,就知道模版是啥了。
题目
先看 BFS 最常见操作:层序遍历
层序遍历
3
/ \
9 20
/ \
15 7
// output:
[
[3],
[9,20],
[15,7]
]
每一层是每一行的输出,说明几个点:
- 你要存储每一层的 node,不然怎么输出
- 从上至下层次输出
先定义结果:vector<vector<int>> res ,然后需要在扫描每一层的时候,把当前层的nodes加入到内层的 vector<int> l :
vector<vector<int>> res; // 总的输出
vector<int> l; // 每一行存储
int n = q.size(); // 每次push进来的都是下一层的全部元素
// n 是当前层的全部数量,不管之后的push,这个就是当前这个时刻的数量
while(n--) {
TreeNode* t = q.front();
q.pop();
l.push_back(t->val);
// push queue
}
res.push_back(l); // 每次循环完都会把当前层的结果,加入到总的结果中
输出完成了,来看看怎么把树遍历起来:
queue<TreeNode*> q; // 全局 queue,父节点进入
if (root) q.push(root);
while(q.size()) {
vector<int> l;
int n = q.size();
while(n--) {
TreeNode* t = q.front();
q.pop();
// 加入 node 输出结果
// 把当前的子节点加入到 queue
if (t->left) q.push(t->left);
if (t->right) q.push(t->right);
}
}
Z型遍历
[
[3],
[20,9],
[15,7]
]
板子基本是这个,区别在于输出:正反正反 -> 在输出的时候判断奇偶即可:
- 声明返回的结果,队列
- 插入 root 到队列
- 循环判断队列不为空
- 弹出队列头部元素,将其左子树node,右子树node,push到队列中
- 把当前访问的元素插入当前层的结果中
- 当前层没有元素 (会记录当前的数量:n,也就是还没插入左右子树的那个瞬间)
- 判断奇偶,是否reverse一下 (所以这不是访问顺序,直接显示顺序,完全可以由reverse完成)
- 插入最终结果
vector<vector<int>> res;
queue<TreeNode*> q;
if (root) q.push(root);
int cnt = 0;
while (q.size()) {
vector<int> l;
int n = q.size();
while (n--) {
auto t = q.front();
q.pop();
if (t->left) q.push(t->left);
if (t->right) q.push(t->right);
l.push_back(t->val);
}
if (cnt % 2 == 1) reverse(l.begin(), l.end());
cnt++;
res.push_back(l);
}
return res;