用Python實現基於依賴關系的排序


依賴關系是開發過程中經常遇到的,例如每個JAVA工程都可以依賴很多其它JAVA工程的制品,在整個進行構建時,就需要考慮這種依賴關系了, 不然總是構建不成功的,本文就以此情景為例,實現一個基於這種依賴關系的多個模塊排序,以便能正常地整個構建成功。

假設有A,B,C,D,E,F六個模塊,它們的依賴關系如下:

A <-- B,C

B <-- D,E

C <-- E

D <-- F

要表達這種抽象的關系,我們可以借助於拓撲圖,如下圖所示:

這種表達方式就比較清晰了,從中可以得出結論,出度為0(即沒有指向其它節點的箭頭)的節點排在最前面,排序的過程就是依次將出度為0的節點移出來,所形成的結果即是最終排序了。

     這里用Python來表達排序過程的話,需要用字典類型來記錄依賴關系,具體代碼如下:

 1 #!python
 2 # coding:GB18030
 3 ###################################################################################################
 4 #
 5 #   基於依賴關系的排序
 6 #   情景:A <-- B,C
 7 #         B <-- D,E
 8 #         C <-- E
 9 #         D <-- F
10 #
11 #
12 ####################################################################################################
13 
14 import os
15 
16 def clearKeyFromVal(key, vals):
17     """從各Value中清除指定的Key
18     相當於在拓撲圖中移出一個節點后,要清除所有與該節點的關聯,即箭頭
19     """
20     for val in vals:
21         if type(val) is tuple and key in val:
22             vl = list(val)  #因為要對元組內容修改,需要轉為list類型
23             ln = vl.index(key)
24             vl.pop(ln)
25             tn = vals.index(val)
26             if len(vl) == 0:
27                 vals[tn] = ""
28             else:
29                 vals[tn] = tuple(vl) #將內容改變后,重新轉回tuple類型
30     return vals
31             
32 
33 
34 def clearNullVal(keys, vals, result_list):
35     """將值為''的鍵值對移出字典(值為""的鍵即為在拓撲圖中出度為0的節點)
36        
37     遞歸調用
38     """
39     if "" in vals:
40         nn = vals.index("")
41         vals.pop(nn)
42         key = keys.pop(nn)
43         result_list.append(key) #移出的鍵,放到結果List中
44         vals = clearKeyFromVal(key, vals) #清除與移出鍵相關聯的箭頭,即需要在各個value中也清除該值
45         return clearNullVal(keys, vals, result_list)  #注意這里要return結果 
46     elif len(vals) == 0:
47         return result_list #移出所有Value后,退出
48     else:
49         print '存在循環依賴'
50         return
51     
52 
53 def sortModules(dic):
54     
55     """根據依賴關系,將多個模塊進行排序,被依賴的模塊要在前"""
56     keys = dic.keys()
57     vals = dic.values()
58     mlist = []
59     for val in vals:
60         if type(val) is tuple:
61             for tv in val:
62                 if tv not in dic:
63                     dic[tv] = "" #將沒有依賴的鍵也添加到字典中,以方便后續對整個字典遞歸處理,逐個將值為""的鍵移出,形成排序結果
64     
65     print dic
66     return clearNullVal(dic.keys(), dic.values(), mlist)
67 
68 
69 if __name__ == "__main__":
70 
71     #通過字典結構來表示依賴關系
72     
73     dic={'A':('B','C'),'B':('D','E'),'C':('E', ), 'D': ('F', )}
74     r_list = sortModules(dic)
75     print r_list

注:1)要注意判斷是否存在循環依賴,即在拓撲圖中形成環,即始終找不到出度為0的節點。

      2)移出節點時,運用了遞歸調用方式。

      3)雖然依賴關系是用字典類型來表達的,但處理過程中,將字典的鍵和值分為兩個列表來處理,同步移出節點

      4)依賴關系,在字典中是用元組作為Value的(因為它是不可變的,即可哈希的),在操作過程中,又適時與列表類型轉換

      5) 一開始先將字典補充完整,即沒有依賴其它的模塊也加進去,為的就是通過遞歸方式,統一操作處理,不然,處理這非規則的情況,也比較麻煩,破壞使用遞歸的條件。

運行結果:

以上便是整個排序過程,如有高見,請不吝賜教


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM