C#实现有向无环图(DAG)拓扑排序
對一個有向無環圖(Directed Acyclic Graph簡稱DAG)G進行拓撲排序,是將G中所有頂點排成一個線性序列,使得圖中任意一對頂點u和v,若邊(u,v)∈E(G),則u在線性序列中出現在v之前。通常,這樣的線性序列稱為滿足拓撲次序(Topological Order)的序列,簡稱拓撲序列。簡單的說,由某個集合上的一個偏序得到該集合上的一個全序,這個操作稱之為拓撲排序.
線性結構概念
總的來說,“線性結構”是一個有序數據元素的集合 線性結構滿足以下特點:
- 集合中必存在唯一“第一個元素”;
- 集合中必存在唯一“最后一個元素”;
- 除了最后一個元素,所有元素均有唯一“后繼結點”;
- 除了第一個元素,所有元素均有唯一“前趨結點”
和我們abp Module很像,第一個加載模塊永遠是其ABP核心模塊,最后一個模塊永遠是我們的啟動模塊
舉例
1.大學課程排序
大學課程的學習是有先后順序的,C語言是基礎,數據結構依賴于C語言,其它課程也有類似依賴關系。這樣的一個課程安排是怎么實現的呢?
2.VS項目編譯順序
假設VS中有三個項目A,B,C,它們的關系如下。VS編譯器是如何判斷三個項目的編譯順序的呢?
A->B->C A引用B B引用C
A->B->C->A 提示循環引用
ABP的Module
ABP中的模塊也是如此,不可循環引用相互依賴A->B B->A X
前面說到ABP中的第一個模塊和最后一個模塊是確定的。
呢么中間的是怎么排序的呢。其實用的是拓撲算法
從圖中可以得知:
1.A模塊是最核心的,不依賴于其他任何模塊
2.D依賴E和B,E依賴B和C,B依賴C和A,C依賴A
那么根據拓撲排序,應該如何排序呢?
1.從圖中找一個沒有前驅指向它的頂點
2.刪除該頂點.以及該頂點的前驅
3.重復步驟 1 and 2 ,直到圖中頂點為空 或者 找不到步驟1中這樣的頂點 為止.
排序如下:
結果就是D->E->B->C->A 排完之后正好對應D依賴E和B,E依賴B和C,B依賴C和A,C依賴A
這個順序在ABP的模塊這看來是行不通的,需要在反轉一次,最先加載A,才行。
C#實現深度優先搜索
有這樣一個DAG圖
如果對它進行排序的話,其實過程是這樣的.
圖中,頂點A是沒有指向它的前驅的,所以從它開始訪問
1.訪問 A
2.訪問 B
3.訪問 C
在訪問了 B 后應該是訪問 B 的另外一個頂點,這里可以是隨機的也可以是有序的,具體取決于你存儲的序列順序,這里先訪問 C 。
4.訪問 E
5.訪問 D
這里訪問 D 是因為 B 已經被訪問過了,所以訪問頂點 D 。
6.訪問 F
因為頂點 C 已經被訪問過,所以應該回溯訪問頂點 B 的另一個有向邊指向的頂點 F 。
7.訪問 G
那么代碼應該如何寫呢?source:需要排序的集合getDepends:一個func委托,用于獲取當前模塊依賴的其他模塊
方法內部維護了一個字典對象Visited 用于存儲已經訪問過的模塊,key表示模塊,value是一個bool,true時表示正在處理,false表示以及處理完成,
處理完成的模塊會加入到sorted集合中
static List<T> MySort<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> getDepends)
{// 訪問過的路徑Dictionary<T, bool> visited = new Dictionary<T, bool>();// 已經排過序的List<T> sorted = new List<T>();foreach (var item in source){Visit<T>(item, getDepends, visited, sorted);}return sorted;
}static void Visit<T>(T item, Func<T, IEnumerable<T>> getDepends, Dictionary<T, bool> visited, List<T> sorted)
{//已經訪問過了if (visited.ContainsKey(item)){bool isVisit = visited[item];if (isVisit == true){throw new Exception("循環引用");}}//未訪問else{visited.Add(item, true);//true :正在訪問 false:訪問完成//獲取所有依賴var depends = getDepends(item);foreach (var depend in depends){Visit(depend, getDepends, visited, sorted);}//訪問完成visited[item] = false;sorted.Add(item);}} 完整demo github
轉載于:https://www.cnblogs.com/zzqvq/p/10260397.html
總結
以上是生活随笔為你收集整理的C#实现有向无环图(DAG)拓扑排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《感鹤》是谁的作品?
- 下一篇: 内衣加盟多少钱啊?