圖的基本概念及存儲方式

圖的基本概念

(Graph)是一種非線性數據結構。
頂點:樹中的元素我們叫做節點;圖中的元素我們叫做頂點(vertex)。
:圖中的一個頂點可以與任意其他頂點建立關係,我們把這種建立的關係叫做邊(edge)。
在這裏插入圖片描述
:以微信爲例,我們可以把每個用戶看成一個頂點,如果兩個用戶之間互加好友,那就在兩者之間建立一條邊。所以整個微信的好友關係就可以用一張圖來表示。其中每個用戶有多少個好友,對應到圖中就是就叫做頂點的度(degree),即跟頂點相連接的邊的條數。

  實際上,微博的好友關係跟微信不同,微博更復雜,因爲微博允許單行關注,即A用戶關注了B用戶,但是B用戶可以不關注A用戶。這種關係也可以用圖來表示。不過此時的關係即邊是有方向的。
  如果A關注B,那麼就畫一條從A指向B的邊。
  如果A和B互相關注,那麼畫一條從A指向B的邊,再畫一條從B指向A的邊。
有向圖:我們把這種邊有方向的圖叫做有向圖,而反之邊沒有方向的就叫做無向圖。
在這裏插入圖片描述
無向圖中有度的概念,表示一個頂點有多少條邊。
有向圖中也有度的概念,分爲入度和出度。
頂點的入度(In-degree):表示有多少條邊指向這個頂點。
頂點的出度(out-degree):表示有多少條邊是以這個頂點爲起點指向其他頂點的。
以微博爲例,入度可以表示有多少粉絲,出度可以表示自己關注了多少人。

實際上,QQ的好友關係跟微博和微信都不同,QQ有親密度,這個親密度其實就是圖中的邊的權重的概念。
帶權圖:在圖中每條邊都有一個權重(weight),可以通過這個權重來表示QQ好友間的親密度。

在這裏插入圖片描述

圖的存儲

鄰接矩陣存儲法

圖最直觀的一種存儲方法就是鄰接矩陣存儲法(Adjacency Matrix)
鄰接矩陣底層依賴於一個二維數組。
  對於無向圖來說,如果頂點i和頂點j之間有邊,我們就將a[i][j]和a[j][i]標記爲1
  對於有向圖來說,如果頂點i到頂點j之間,有一條箭頭從頂點i指向頂點j的邊,那麼我們就將
a[i][j]標記爲1,同理,如果有一條箭頭從頂點j指向頂點i的邊,那麼我們就將a[j][i]標記爲1。
  對於帶權圖,數組中就存儲相應的權重。
在這裏插入圖片描述

  使用鄰接矩陣來存儲圖,確實很簡單直接,但是非常浪費空間。
  比如對於無向圖來說,如果a[i][j]=1,那麼a[j][i]肯定也等於1.實際上我們只需要存儲一個就可以了。也就是說,無向圖中我們可以用對角線將其劃分爲上下兩部分,那麼我們只需要利用上下兩部分就足夠了,剩下一半就浪費了。
  還有,如果存儲的圖示稀疏圖(Sparse Matrix),即頂點很多但是每個頂點的邊並不多。這種情況下鄰接矩陣存儲法更加浪費空間了。
  比如說,微信用戶有很多好幾個億,也就是有好幾個億的頂點,但是每個用戶也就幾百好友不等,那麼絕大多數的存儲空間就浪費了。

鄰接矩陣存儲法的優點:簡單直接、基於數據訪問友好、矩陣計算方便。

鄰接表存儲法

鄰接表存儲法(Adjacency List)跟散列表相似,如圖,每個頂點對應一條鏈表,鏈表中存儲的是跟這個頂點連接的其他頂點,下圖是一個有向圖鄰接表的存儲,每個頂點對應鏈表存儲的是這個頂點所指向的其他頂點,可以用來表示自己關注的微博用戶。無向圖類似。

在這裏插入圖片描述
  其實鄰接矩陣存儲法簡單直接,耗費內存,但是速度比較快。而鄰接表空間利用率高但查找速度相對慢。這就是空間和時間相互交換的思想的體現。
  比如我們想確定一個頂點是否有到另一個頂點的邊,利用鄰接表存儲方式,就得遍歷原始頂點對應的那條鏈表。由於鏈表存儲方式對緩存不友好,相對於鄰接矩陣存儲法查找效率就偏低了。但是不要緊,可以升級改造這條鏈表爲其他支持快速crud的數據結構比如跳錶、紅黑樹這種平衡二叉查找樹等。或者改造爲動態有序數組利用二分法查找定位頂點是否存在。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章