《数据结构与算法分析:C语言描述》复习——第九章“图论”——拓扑排序

2014.07.04 17:23

简介:

  我们考虑一种特殊的图:

    1. 有向图

    2. 只有一个连通分量

    3. 不存在环

  那么这样的图里,必然可以找到一种排序方式,来确定谁在谁的“前面”。

  简单的来说可以这么理解:如果存在一条边a->b,那么a顶点就在b的前面。

  下面我们通过例子来看看拓扑排序的过程,确定所有的顶点中,谁排在谁的前面。

图示:

  下面是一个图,符合上面所提出的三个条件,因此可以进行拓扑排序。我们关注每个顶点的入度,表示这个顶点被指向的次数

  

  每次我们都选出一个入度为0的顶点,因为入度为0的顶点是没有被任何边指向的。“被指向”就代表排在后面。

  比如从目前的图看来,C->E代表顶点E排在顶点C之后。

  

  把入度为0的顶点去除后,同时去除包含它们的边。入度为0的顶点可能不止一个,所以这些点的排序也是并列的。

  

  继续去掉入度为0的顶点并且把它们的排序记录下来,同时去掉对应的边。直至所有顶点都去掉为止。

  

  

  当所有顶点都去掉了,排序也就完成了。

  实际上,即使图的连通分量不止一个排序也可以进行,只是不同连通分量之间的排序是互不影响的。只要是无环有向图,都可以进行拓扑排序。

实现:

 1 // A simple illustration for topological sort. Graph represented by adjacency matrix.
 2 #include <iostream>
 3 #include <queue>
 4 #include <vector>
 5 using namespace std;
 6 
 7 void topologicalSort(const vector<vector<bool> > &graph, vector<int> &order)
 8 {
 9     int n;
10     int i, j;
11     vector<int> indegree;
12     queue<int> q;
13     
14     n = (int)graph.size();
15     indegree.resize(n, 0);
16     
17     for (i = 0; i < n; ++i) {
18         for (j = 0; j < n; ++j) {
19             if (graph[i][j]) {
20                 ++indegree[j];
21             }
22         }
23     }
24     
25     for (i = 0; i < n; ++i) {
26         if (indegree[i] == 0) {
27             q.push(i);
28             break;
29         }
30     }
31     
32     while (!q.empty()) {
33         i = q.front();
34         q.pop();
35         order.push_back(i);
36         for (j = 0; j < n; ++j) {
37             if (graph[i][j] && (--indegree[j] == 0)) {
38                 q.push(j);
39             }
40         }
41     }
42     
43     indegree.clear();
44 }
45 
46 int main()
47 {
48     vector<vector<bool> > graph;
49     vector<int> order;
50     int n;
51     int nk;
52     int i, j;
53     int tmp;
54     
55     while (cin >> n && n > 0) {
56         graph.resize(n);
57         for (i = 0; i < n; ++i) {
58             graph[i].resize(n, false);
59         }
60         
61         for (i = 0; i < n; ++i) {
62             cin >> nk;
63             for (j = 0; j < nk; ++j) {
64                 cin >> tmp;
65                 graph[i][tmp] = true;
66             }
67         }
68         
69         topologicalSort(graph, order);
70         
71         if ((int)order.size() == n) {
72             for (i = 0; i < n; ++i) {
73                 cout << order[i] << ' ';
74             }
75             cout << endl;
76         } else {
77             cout << "The graph has a cycle." << endl;
78         }
79         
80         for (i = 0; i < n; ++i) {
81             graph[i].clear();
82         }
83         graph.clear();
84         order.clear();
85     }
86     
87     return 0;
88 }
原文地址:https://www.cnblogs.com/zhuli19901106/p/3824922.html