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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图论(六)图的两种表示方法

發(fā)布時間:2025/3/20 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图论(六)图的两种表示方法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

如果要用圖來解決問題,首先我們必須采用某種數(shù)據(jù)結(jié)構(gòu)來存儲和表示“圖”。相對于數(shù)組、鏈表等來說,圖的存儲結(jié)構(gòu)就復雜的多了。

  • 首先,圖上的任何一個頂點都可以被看作是第一個頂點,任意頂點的鄰接頂點之間也不存在次序關系。還記得在《圖論(一)基本概念》中的“同構(gòu)圖”吧,圖的形狀可以千變?nèi)f化的。因此也就無法以數(shù)據(jù)元素在內(nèi)存中的物理位置來表示元素之間的關系,也就是說,圖不可能用數(shù)組這樣簡單的順序存儲結(jié)構(gòu)來表示。
  • 其次,如果使用鏈表一樣的鏈式存儲結(jié)構(gòu),不同頂點的鄰接頂點數(shù)量是不一樣的,相差可能很大,如何在操作和效率之間尋求平衡是個大難題。

不過不用擔心,計算機科學界不缺乏牛人,前輩們早就為我們設計好了,而且方法不止一種,發(fā)明了大量的圖表示法,甚至還有專門從事圖表示法的研究員(Jeremy P.Spinrad),還寫過一本書《Efficient Graph Representations》。

盡管有大量的圖表示法可用,但我們需要掌握的,也是最常用的、最著名的,可用性和普及率都最高的,只有兩類:鄰接表法和鄰接矩陣法。都帶有“鄰接”兩字,這是數(shù)學語言,大白話的意思就是“鄰居”。

(1)鄰接表

鄰接表的核心思想就是針對每個頂點設置一個鄰居表。

以上面的圖為例,這是一個有向圖,分別有頂點a, b, c, d, e, f, g, h共8個頂點。使用鄰接表就是針對這8個頂點分別構(gòu)建鄰居表,從而構(gòu)成一個8個鄰居表組成的結(jié)構(gòu),這個結(jié)構(gòu)就是我們這個圖的表示結(jié)構(gòu)或者叫存儲結(jié)構(gòu)。

a, b, c, d, e, f, g, h = range(8) N = [{b, c, d, e, f}, # a 的鄰居表{c, e}, # b 的鄰居表ozvdkddzhkzd, # c 的鄰居表{e}, # d 的鄰居表{f}, # e 的鄰居表{c, g, h}, # f 的鄰居表{f, h}, # g 的鄰居表{f, g}] # h 的鄰居表

這樣,N構(gòu)成了一個鄰居節(jié)點集。可以通過N對圖進行操作了。

# 頂點f的鄰居頂點 print(N[f]) # 頂點g是否是a的鄰居頂點 print(g in N[a]) # 頂點a的鄰居頂點個數(shù) print(len(N[a]))

輸出結(jié)果:

{2, 6, 7} False 5

注意:每個頂點的鄰居表都是一個集合(set),為什么用set,因為不能重復存儲鄰居頂點,這是一個非常自然的選擇。那么,可不可以用list,當然可以。用字典呢,當然也可以,甚至在表示帶權(quán)重值的圖時,使用字典表示更合理。

N = [{b: 1, c: 2, d: 1, e: 2, f: 3}, # a 的鄰居表{c: 1, e: 2}, # b 的鄰居表{d: 3}, # c 的鄰居表{e: 1}, # d 的鄰居表{f: 2}, # e 的鄰居表{c: 1, g: 1, h: 1}, # f 的鄰居表{f: 1, h: 2}, # g 的鄰居表{f: 1, g: 2}] # h 的鄰居表# 邊(a,f)的權(quán)重 if f in N[a]:print(N[a][f])

輸出結(jié)果:

3

需要注意的是,不管鄰居表是用set,list,還是dict,都是鄰接表的各種變形,最終使用哪個取決于這個圖本身是什么,我們要用這個圖干什么。實際應用中我們可以針對圖本身特點和我們要解決問題特點針對性的構(gòu)建圖的表示結(jié)構(gòu)。

(2)鄰接矩陣

鄰接矩陣的核心思想是針對每個頂點設置一個表,這個表包含所有頂點,通過True/False來表示是否是鄰居頂點。
還是針對上面的圖,分別有頂點a, b, c, d, e, f, g, h共8個頂點。使用鄰接矩陣就是針對這8個頂點構(gòu)建一個8×8的矩陣組成的結(jié)構(gòu),這個結(jié)構(gòu)就是我們這個圖的表示結(jié)構(gòu)或存儲結(jié)構(gòu)。

a, b, c, d, e, f, g, h = range(8) N = [[0, 1, 1, 1, 1, 1, 0, 0], # a的鄰接情況[0, 0, 1, 0, 1, 0, 0, 0], # b 的鄰居表[0, 0, 0, 1, 0, 0, 0, 0], # c 的鄰居表[0, 0, 0, 0, 1, 0, 0, 0], # d 的鄰居表[0, 0, 0, 0, 0, 1, 0, 0], # e 的鄰居表[0, 0, 1, 0, 0, 0, 1, 1], # f 的鄰居表[0, 0, 0, 0, 0, 1, 0, 1], # g 的鄰居表[0, 0, 0, 0, 0, 1, 1, 0]] # h 的鄰居表

同樣,可以對N進行圖操作了,操作方式與鄰接表方式有所不同。

# 頂點g是否是a的鄰居頂點 print(N[a][g])# 頂點a的鄰居頂點個數(shù) print(sum(N[a]))# 頂點a的鄰居頂點 neighbour = [] for i in range(len(N[f])): if N[f][i]: neighbour.append(i) print(neighbour)

輸出結(jié)果:

0 5 [2, 6, 7]

在鄰接矩陣表示法中,有一些非常實用的特性。

  • 首先,可以看出,該矩陣是一個方陣,方陣的維度就是圖中頂點的數(shù)量,同時還是一個對稱矩陣,這樣進行處理時非常方便。
  • 其次,該矩陣對角線表示的是頂點與頂點自身的關系,一般圖不允許出現(xiàn)自關聯(lián)狀態(tài),即自己指向自己的邊,那么對角線的元素全部為0;
  • 最后,該表示方式可以不用改動即可表示帶權(quán)值的圖,直接將原來存儲1的地方修改成相應的權(quán)值即可。當然, 0也是權(quán)值的一種,而鄰接矩陣中0表示不存在這條邊。出于實踐中的考慮,可以對不存在的邊的權(quán)值進行修改,將其設置為無窮大或非法的權(quán)值,如None,-99999/99999等。

最后總結(jié)下,鄰接表和鄰接矩陣兩種表示方法各有特點,具體使用哪個應該針對具體問題具體分析。但事實上,如果不是特別巨大無比的圖,用不著費勁思考,用哪種都可以的。

總結(jié)

以上是生活随笔為你收集整理的图论(六)图的两种表示方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。