數據結構-05 |圖

 

1. 圖的概念

 (Graph)另一種非線性表數據結構。

樹中的元素稱爲節點,圖中的元素叫作頂點(vertex)。圖中的一個頂點可以與任意其他頂點建立連接關係。這種建立的關係叫作(edge)。跟頂點相連接的邊的條數叫作頂點的(degree)。

有方向的圖叫作“有向圖”。以此類推,我們把邊沒有方向的圖就叫作“無向圖”

                                                                

 

 無向圖中有“度”這個概念,表示一個頂點有多少條邊。在有向圖中,把度分爲入度(In-degree)和出度(Out-degree)。

  頂點的入度,表示有多少條邊指向這個頂點;頂點的出度,表示有多少條邊是以這個頂點爲起點指向其他頂點。

帶權圖(weighted graph)。在帶權圖中,每條邊都有一個權重(weight),我們可以通過這個權重來表示 QQ 好友間的親密度。

                                                              

 

 

2. 圖的存儲

2.1 鄰接矩陣(Adjacency Matrix)

圖最直觀的一種存儲方法就是,鄰接矩陣(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),也就是說,頂點很多,但每個頂點的邊並不多,那鄰接矩陣的存儲方法就更加浪費空間了。

優點:

  首先,鄰接矩陣的存儲方式簡單、直接,因爲基於數組,所以在獲取兩個頂點的關係時,就非常高效。

  其次,用鄰接矩陣存儲圖的另外一個好處是方便計算。這是因爲,用鄰接矩陣的方式存儲圖,可以將很多圖的運算轉換成矩陣之間的運算。比如求解最短路徑問題時會提到一個Floyd-Warshall 算法,就是利用矩陣循環相乘若干次得到結果。

2.2 鄰接表(Adjacency List)

每個頂點對應一條鏈表,鏈表中存儲的是與這個頂點相連接的其他頂點。另外我需要說明一下,圖中畫的是一個有向圖的鄰接表存儲方式,每個頂點對應的鏈表裏面,存儲的是指向的頂點。對於無向圖來說,也是類似的,不過,每個頂點的鏈表中存儲的,是跟這個頂點有邊相連的頂點

                                        

 

 

鄰接矩陣存儲起來比較浪費空間,但是使用起來比較節省時間。相反,鄰接表存儲起來比較節省空間,但是使用起來就比較耗時間。(時間、空間複雜度互換的設計思想)

就像圖中的例子,如果我們要確定,是否存在一條從頂點 2 到頂點 4 的邊,那我們就要遍歷頂點 2 對應的那條鏈表,看鏈表中是否存在頂點 4。而且,我們前面也講過,鏈表的存儲方式對緩存不友好。所以,比起鄰接矩陣的存儲方式,在鄰接表中查詢兩個頂點之間的關係就沒那麼高效了。

在散列表那幾節裏,我講到,在基於鏈表法解決衝突的散列表中,如果鏈過長,爲了提高查找效率,我們可以將鏈表換成其他更加高效的數據結構,比如平衡二叉查找樹等。我們剛剛也講到,鄰接表長得很像散列。所以,我們也可以將鄰接表同散列表一樣進行“改進升級”。

我們可以將鄰接表中的鏈表改成平衡二叉查找樹。實際開發中,我們可以選擇用紅黑樹。這樣,我們就可以更加快速地查找兩個頂點之間是否存在邊了。當然,這裏的二叉查找樹可以換成其他動態數據結構,比如跳錶、散列表等。除此之外,我們還可以將鏈表改成有序動態數組,可以通過二分查找的方法來快速定位兩個頂點之間否是存在邊。

3. 應用

    微博、微信是兩種“圖”,前者是有向圖(入度和出度概念),後者是無向圖(度的概念)。

 微博,微博允許單向關注,微博的入度就表示有多少粉絲,出度就表示關注了多少人。

QQ 不僅記錄了用戶之間的好友關係,還記錄了兩個用戶之間的親密度  ---  帶權圖(weighted graph)。在帶權圖中,每條邊都有一個權重(weight),我們可以通過這個權重來表示 QQ 好友間的親密度。

 

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