拓撲排序 - Topological Sort
有向圖的拓撲排序是它的頂點的線性排序,比如任意 邊 uv 對於 它的頂點 u 和 頂點 v, u v按照 u 在前 v在後的順序排序。 注意:只有 有向無環圖 (DAG) 才有拓撲排序, 如果一個圖 是有環 的圖那麼它不存在拓撲排序。
在現實生活中, 拓撲排序能被用於以下場景。 比如任意頂點都是要完成的任務,並且每個邊 都是 完成一個任務才能繼續完成下一個任務的 一種限制。 所以在這種情況下, 對這個圖的拓撲排序就是完成所有任務的序列佇列。
The graph shown to the left has many valid topological sorts, including:
|
Kahn's 演算法。演算法複雜度為 線性時間(邊的數 + 頂點的數)
L - 一個空的list,作為最後返回值
S - 一個Set包含所有的點,這些點沒有incoming 的邊。
while S is non-empty do:
remove a node n from S
add n to the list of L
for each node m with an edge e from n to m do:
remove edge e from graph
if m has no other incoming edges then:
insert m into S
if graph has edges then:
return error ( 有環圖,不能進行拓撲排序 )
else
return L ( 解 )
Java 版本實現
package TopologicalSorting;
import java.util.*;
//this indicate an edge
//from node_2 point to node_1
class Pair {
String node_1;
String node_2;
Pair(String node_1, String node_2) {
this.node_1 = node_1;
this.node_2 = node_2;
}
}
public class KahnAlgorithm {
public static ArrayList<String> Kahn (ArrayList<Pair> graph) {
ArrayList<String> L = new ArrayList<String> (); //to store the result
ArrayList<String> S = new ArrayList<String> (); //set of nodes with no incoming edges
S = findNoIncomingEdges (graph);
while (!S.isEmpty()) {
String n = S.remove(0); //remove node n from S
L.add(n); //add node n to L
//find all of the nodes that have an edge from n to m
for (String m : findNodes (n,graph)) {
//remove edge e from graph
graph = removeEdge (m, n, graph);
//if m does not has incoming edge
if (!hasIncomingEdge(m, graph)) {
//insert m into S
S.add(m);
}
}
}
//still has edge left
if (!graph.isEmpty()) {
return null;
}
return L;
}
//find the nodes with no incoming edge
public static ArrayList<String> findNoIncomingEdges (ArrayList<Pair> graph) {
ArrayList<String> result = new ArrayList<String> ();
Set<String> grandSet = new HashSet<String> (); //all node in graph
//construct grand set
for (Pair temp : graph) {
grandSet.add(temp.node_1);
grandSet.add(temp.node_2);
}
result.addAll(grandSet);
for (Pair temp : graph) {
if (grandSet.contains(temp.node_1)) {
result.remove(temp.node_1);
}
}
return result;
}
//find the nodes and remove all of the edges with n and m
public static ArrayList<String> findNodes (String n, ArrayList<Pair> graph) {
ArrayList<String> result = new ArrayList<String> ();
//find the nodes that point from n to m
for (Pair p : graph) {
if (p.node_2.compareTo(n) == 0) {
result.add(p.node_1);
}
}
return result;
}
//remove edge from graph
public static ArrayList<Pair> removeEdge (String m, String n, ArrayList<Pair> graph) {
ArrayList<Pair> result = new ArrayList<Pair> ();
result = (ArrayList<Pair>) graph.clone();
for (Pair temp : graph) {
if (temp.node_1.compareTo(m) == 0
&& temp.node_2.compareTo(n) == 0) {
result.remove(temp);
}
}
return result;
}
//check whether it has incoming edge
public static boolean hasIncomingEdge (String m, ArrayList<Pair> graph) {
for (Pair temp : graph) {
if (temp.node_1.compareTo(m) == 0) {
return true;
}
}
return false;
}
}
有問題歡迎指出。
相關文章
- 拓撲排序排序
- 拓撲排序,YYDS排序
- 圖論——拓撲排序圖論排序
- 筆記:拓撲排序筆記排序
- 拓撲排序小結排序
- Reward (圖論+拓撲排序)圖論排序
- AOV網與拓撲排序排序
- 【筆記/模板】拓撲排序筆記排序
- DFS實現拓撲排序排序
- 拓撲排序就這麼回事排序
- 演算法-圖論-拓撲排序演算法圖論排序
- 有向圖的拓撲排序——DFS排序
- (set+拓撲排序) CF1572A Book排序
- 圖解拓撲排序+程式碼實現圖解排序
- 圖的拓撲排序詳解與實現排序
- 拓撲排序 (BFS )DAG (有向無環圖)排序
- POJ 1094 Sorting It All Out Floyd_Washall+Topological_sort
- VOL.2 拓撲排序與關鍵路徑排序
- 【Tarjan 拓撲排序 dp】P3387 【模板】縮點排序
- 拓撲排序詳解(梅開二度之dfs版按字典序輸出拓撲路徑+dfs版輸出全部拓撲路徑排序
- Noc拓撲
- 洛谷P3953 逛公園(dp 拓撲排序)排序
- 牛客 51011 可達性統計(拓撲排序,bitset)排序
- sort排序排序
- 【BZOJ-1565】植物大戰殭屍 拓撲排序 + 最小割排序
- Day2 尤拉路,拓撲排序和差分約束排序
- Leetcode 1691. 堆疊長方體的最大高度(拓撲排序 + DP)LeetCode排序
- 堆排序 Heap Sort排序
- Elasticsearch script sort 排序Elasticsearch排序
- 快速排序 (Quick Sort)排序UI
- Collections sort()排序方法排序
- StratoVirt 的 vCPU 拓撲(SMP)
- 網路拓撲結構
- BZOJ2535: [Noi2010]Plane 航空管制2(拓撲排序 貪心)排序
- Android程式設計師會遇到的演算法(part 7 拓撲排序)Android程式設計師演算法排序
- 網路拓撲圖:網路拓撲圖介紹及線上製作
- 藍橋杯 卡勒沃夫之弱水路三千(提高型) 拓撲排序+Map排序
- 演算法資料結構 | 圖論基礎演算法——拓撲排序演算法資料結構圖論排序
- 希爾排序(Shell Sort)排序