树与图的广度优先遍历、拓扑排序

树与图的广度优先遍历:用一个队列来实现。起初,队列中仅包含一个起点,在遍历过程中,我们不断从队头取出一个节点 x ,对于 x 面对的多条分支,把沿着每条分支到达的下一个节点(如果未访问过)插入队尾,重复上述过程直至队列为空。

void bfs(){
    memset(d, 0, sizeof d);
    queue<int> q;
    q.push(1), d[1] = 1;
    while(q.size() > 0){
        int x = q.front();
        q.pop();
        for(int i = head[x]; i; i = next[i]){
            int y = ver[i];
            if(d[y]) continue;
            d[y] = d[x] + 1;
            q.push(y);
        }
    }
}

在上面的代码中,我们顺带求出了一个 d 数组。对于一棵树来讲, d[x] 就是点 x 在树中的深度。对于一张图来讲,d[x] 被称为点 x 的层次。广度优先遍历是一种按照层次顺序进行访问的方法,它具有如下两个性质:(1)、在访问完所有的第 i 层节点后,才会开始访问第 i+1 层节点。(2)、任意时刻,队列中最多有两个层次的节点。所有第 i 层节点排在第 i + 1 层节点之前。

拓扑排序:给定一张有向无环图,若一个由图中所有顶点构成的序列 A 满足:对于图中的每条边 (x, y),x 在 A 中都出现在 y 之前,则称 A 是该有向无环图顶点的一个拓扑序。求解序列 A 的过程为拓扑排序。

拓扑排序的思想非常简单,我们只需要不断选择图中入度为为 0 的节点,然后把 x 连向的点的入度减 1。结合广度优先遍历的框架可以高效的实现这个过程:(1)、建立空的拓扑序列 A。 (2)、预处理出suo’所有点的入度 deg[i],起初把所有入度为 0 的顶点入队。(3)、取出队列节点 x ,把 x 加入拓扑序列 A 的末尾。(4)、对于从 x 出发的每条边 (x, y),把 deg[y]减 1 。若被减为 0,则把 y 入队。(5)、重复第 3~4 步直到直到队列为空,此时 A 即为所求。

拓扑排序可以判定一个有向图中是否存在环。我们对于任意有向图执行上述过程,在完成后检查序列 A 的长度。若 A 序列的长度小于图中顶点的数量,则说明图中某些点未访问到,进而说明图中存在环。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 1000+7;
int head[maxn],ver[maxn];
int edge[maxn],next[maxn];
int tot,cnt;
int deg[maxn], a[maxn];
int n,m;
void add(int x, int y) {
    ver[++tot]=y;
    next[tot] = head[x], head[x] = tot;
    deg[y]++;
}

void toposort() {
    queue<int> q;
    for(int i = 1; i <= n; i++)
        if(deg[i] == 0) q.push(i);
    while(q.size() > 0){
        int x = q.front();
        q.pop();
        a[++cnt] = x;
        for(int i = head[x]; i; i = next[i]){
            int y = ver[i];
            deg[y]--;
            if(deg[y] == 0)
                q.push(y);
        }

    }
}
int main()
{
    int x, y;
    scanf("%d %d",&n, &m);
    while(m--){
        scanf("%d %d",&x, &y);
        add(x,y);
    }
    toposort();
    for(int i = 1; i <= cnt-1; i++){
        printf("%d ", a[i]);
    }
    printf("%d\n", a[cnt]);
    return 0;
}

 

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/qq_37867156/article/details/82492319
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞