使用鄰接表進行拓撲排序的演算法說明

2021-07-25 17:30:40 字數 2826 閱讀 3722

講拓撲排序的概念,先來回顧乙個大家熟悉的東西:技能樹(圖)!

因為這個特好理解,玩過暗黑或其他rpg遊戲的都應該見過類似的技能樹,一句話,就是學習高階技能前需要先學習之前的低階技能。

乙個技能樹其實是乙個簡單的圖,你可以把它再變化一下就是一張圖,即讓一些高階技能間也發生聯絡,使得學習一種高階技能可以通過多種途徑,於是這就是乙個正兒八經的圖了。

拓撲排序就是要排出這樣乙個線性序列,即「高等技能」一定在「初等技能」的後面,絕不會出現「高等技能」學完後再學「初等技能 」的情況。

言歸正傳,學習拓撲排序,需要知道如下幾個概念。

1、圖:可以理解為網路,乙個由點和線組成的網路,線段有方向稱為有向圖,線段無方向稱為無向圖。

2、aov網路:就是 activity on vertex network的簡稱,頂點活動網,它是乙個有向無環圖。有向:就是指有先後順序,比如技能樹中,學習技能有先後順序。無環:就是圖裡面沒有首尾相接的「圈」,比如技能樹中學完高技能後總不能又回到低技能的學習吧?

3、鄰接矩陣:這是一種圖的儲存方法,用乙個二維陣列來來儲存圖的結構。該矩陣裡只有0和1,aij 處為1代表從i到j有一條連線。比如如下二維矩陣,就表示了乙個對應的圖(這裡規定它是有向圖)

4、鄰接表:這是另一種圖的儲存方法,稍微複雜一點,利用到了陣列和鍊錶還有結構體,和佇列、棧、鍊錶類似,鄰接表可以看成是一種單獨的資料結構。包括乙個縱向結構體陣列(縱表)和橫向鍊錶(橫表),它表示了與上面相同的乙個圖,結構如下所示。

一般我們是通過鄰接矩陣來構造鄰接表,之後拓撲排序時真正使用的是鄰接表,因為它包含了比鄰接矩陣更多的資訊,並且更便於之後的排序操作。

縱表結構體包含了1個前繼數量、乙個節點資料和1乙個結構體指標。前繼表示有多少個其它節點指向了該節點。指標用來指向該節點所對應的橫表,橫表記錄了該節點所有指向節點的位置(用乙個索引值表示,即縱表陣列下標)。

struct node                 //縱表結構體

橫表結構體中包含乙個節點索引值和乙個結構體指標。索引值記錄了該節點是縱表中的第幾個節點,指標指向下乙個橫表節點,結構體形式如下。

struct link                 //橫表結構體

上述4個概念比較重要,特別是鄰接表的概念,是資料結構裡的乙個綜合應用,也是下述拓撲排序的主要操作物件。

現在開始排序,這只是一種可能的排序方法,一幅圖的拓撲排序能有多種結果。

還是上面所示的圖,這個圖的一種可能排序為:1 4 3 6 2 5 ,可以驗證一下,應該沒錯,我們輸出的就是這個結果。

演算法結構如下:

while (能輸出)

當把縱表中的數全部遍歷完,輸出的順序即一次拓撲排序。

到此為止,拓撲排序的一般演算法就講完了,接下來說的是提公升效率的一點改進。

如何做到演算法執行過程中,節點輸出不重複且迴圈次數少?

方法有很多種,不同方法會產生不同輸出結果,如果對排序結果沒有額外要求的話,這些結果都是正確的拓撲排序。

一種實現方法就是:

將縱表中前繼為0的點組成乙個棧,每次從棧裡取節點,這種方法同樣能夠遍歷整個縱表,並且不需要耗費額外的儲存開銷(不需要再建立乙個鍊錶結構的棧,縱表結構體中的count值可以記錄節點在棧中的位置,這是一種資料復用的思想,因為凡是conut值被減為0的節點,該count變數都不再具有其它用途,可以被重複利用來記錄節點在棧中的位置)

以上面的鄰接表為例:

演算法開始時:

1、從縱表開始,找到前繼為0的點,壓棧,此時棧裡只有1,

2、從棧頂取乙個節點(彈棧),此時就是1,輸出節點值1。

3、將其橫表所對應的節點count值減1,凡是count值被減為0的壓棧

此時,按照操作順序,縱表中2號節點的count值先被減為0,所以在棧底,隨後依次是3號節點和4號節點,至此第一條橫表操作完畢,棧結構如下圖。

3、再次從棧裡彈出乙個節點,此時是4,將對應橫表節點的count值減1,減過之後,沒有新的count為0的點,所以沒有新元素進棧。

4、不斷重複,繼續彈棧、減去橫表對應節點count值、若有0就壓棧,直到最後,所有棧元素輸出空,即排序完成。

這種方法輸出的節點順序是1-4-3-6-2-5,這也是從棧裡彈出的順序,這種方法好處是遍歷次數少、額外儲存空間開銷少。

演算法導論 鄰接表儲存的拓撲排序

在鄰接表儲存結構中,為了便於檢查每個頂點的入度,可在頂點表中增加乙個入度域 id 這樣的鄰接表如下圖所示,這樣只需對由n個元素構成的頂點表進行檢查就能找出入度為0的頂點。為了避免對每個入度為0的頂點重複訪問,可用乙個鏈棧來儲存所有入度為0的頂點。在進行拓撲排序前,只要對頂點表進行一次掃瞄,便可將所有...

拓撲排序 C語言 鄰接表

資料結構 typedef struct side 邊 side,slink typedef struct vertex 頂點 vertex,adjlist 20 typedef struct graph 圖 graph,glink 建立 void creategraph glink g printf...

基於鄰接表的拓撲排序實現

由於 比較簡單,就直接貼出來了 1 include 2 include 3 include 4 include 5 using namespace std 67 8enum graphtype9 1516 結點顏色代表遍歷情況 17enum colortype18 2324 template25 c...