日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C#实现有向无环图(DAG)拓扑排序

發布時間:2023/11/27 生活经验 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#实现有向无环图(DAG)拓扑排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

對一個有向無環圖(Directed Acyclic Graph簡稱DAG)G進行拓撲排序,是將G中所有頂點排成一個線性序列,使得圖中任意一對頂點u和v,若邊(u,v)∈E(G),則u在線性序列中出現在v之前。通常,這樣的線性序列稱為滿足拓撲次序(Topological Order)的序列,簡稱拓撲序列。簡單的說,由某個集合上的一個偏序得到該集合上的一個全序,這個操作稱之為拓撲排序.

線性結構概念

總的來說,“線性結構”是一個有序數據元素的集合 線性結構滿足以下特點:

  1. 集合中必存在唯一“第一個元素”;
  2. 集合中必存在唯一“最后一個元素”;
  3. 除了最后一個元素,所有元素均有唯一“后繼結點”;
  4. 除了第一個元素,所有元素均有唯一“前趨結點”

和我們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)拓扑排序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。