📅  最后修改于: 2023-12-03 14:54:48.714000             🧑  作者: Mango
这道题涉及到数据结构和算法中的树的遍历,需要使用深度优先遍历(DFS)和广度优先遍历(BFS)两种方式完成。
给定一棵树,树的编号为1~n。每个节点有一个权值Weight[i],权值均为正整数。现在,按照以下两种方式对树进行遍历:
求这两种情况下的遍历顺序。
首先,树的遍历可以用DFS和BFS两种方式实现。定义一个visited
数组表示当前节点是否访问过,以及一个max1
和max2
数组表示当前节点的子节点权值的前两大值。
对于DFS遍历,可以首先排序整个树,保证每次遍历到的节点是权值最小的,然后从根节点开始,遍历每个节点,并使用递归实现子树的遍历。每遍历到一个节点,就按照权值对其子节点进行排序,然后优先遍历权值最大的两个子节点,并继续递归。
对于BFS遍历,同样可以从编号最小的点开始,使用一个priority_queue
对每个节点的子节点进行排序,每次取出权值最大的两个子节点,并将其加入队列。然后继续下一层的遍历。
最后,输出DFS和BFS的遍历结果。
### DFS遍历
- 全局变量:visited[], max1[], max2[]
- 函数名:void dfs(int i)
- 函数功能:DFS遍历整个树,并求出每个节点的权值前两大的子节点
- 入参:i表示当前节点的编号
- 使用方法:从根节点开始调用
代码:
void dfs(int i) {
visited[i] = true;
priority_queue<int> q;
// 遍历当前节点的所有子节点
for (int j = head[i]; j != -1; j = e[j].next) {
int v = e[j].to;
if (!visited[v]) {
dfs(v);
q.push(max1[v]);
q.push(max2[v]);
}
}
// 取出当前节点的前两大子节点
int cnt = 0;
while (!q.empty() && cnt < 2) {
int p = q.top();
q.pop();
if (p > 0) {
cnt++;
if (max1[i] < p) {
max2[i] = max1[i];
max1[i] = p;
} else if (max2[i] < p) {
max2[i] = p;
}
}
}
}
### BFS遍历
- 全局变量:visited[], max1[], max2[]
- 函数名:void bfs(int i)
- 函数功能:BFS遍历整个树,并求出每个节点的权值前两大的子节点
- 入参:i表示从哪个节点开始遍历
- 使用方法:从根节点开始调用
代码:
void bfs(int i) {
queue<int> q;
q.push(i);
while (!q.empty()) {
int u = q.front();
q.pop();
visited[u] = true;
priority_queue<int> pq;
// 对当前节点的子节点进行排序,并加入优先队列
for (int j = head[u]; j != -1; j = e[j].next) {
int v = e[j].to;
if (!visited[v]) {
pq.push(e[j].w);
}
}
// 取出当前节点的前两大子节点
int cnt = 0;
while (!pq.empty() && cnt < 2) {
int p = pq.top();
pq.pop();
if (p > 0) {
cnt++;
if (max1[u] < p) {
max2[u] = max1[u];
max1[u] = p;
} else if (max2[u] < p) {
max2[u] = p;
}
}
}
// 将当前节点的子节点加入队列
for (int j = head[u]; j != -1; j = e[j].next) {
int v = e[j].to;
if (!visited[v]) {
q.push(v);
}
}
}
}
## 参考资料
- 《算法竞赛入门经典》