十五、圖(graph)
阿新 • • 發佈:2018-12-05
引入
社交網路,如何儲存微博、微信等這些社交網路的好友關係?
==》圖
一、圖(Graph)的相關概念
- 圖:複雜的非線性表結構;
- 頂點(vertex):圖中的元素;
- 邊(edge):圖中一個頂點可以與任意其他頂點建立連線關係。
- 頂點的度(degree):與頂點相連線的邊的條數
- 無向圖:邊沒有方向的圖;
- 有向圖:邊存在方向的圖;
- 有向圖中度分為入度(in-degree)和出度(out-degree)
- 入度:表示有多少條邊指向這個頂點;
- 出度:表示有多少條邊是以這個頂點為起點指向其他節點。
- 以微博為例,入度:粉絲數,出度:關注人數
- 帶權圖(weighted graph):每條邊都有一個權重(weight),例如:QQ好友之間的親密度。
二、圖的儲存
1、鄰接矩陣儲存方法
- 直觀、簡單、方便計算、高效獲取兩個頂點關係,但較為浪費儲存空間(儲存的是稀疏圖( Sparse 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。
2、鄰接表(Adjacent List)儲存方法
- 每個頂點對應一條連結串列,連結串列中儲存的是與該頂點相連的其他節點;
- 在有向圖的鄰接表儲存方式中,每個頂點對應的連結串列中,儲存的是指向的頂點;
- 在無向圖的鄰接表儲存方式中,每個頂點對應的連結串列中,儲存的是跟該頂點有邊相鄰的頂點;
==》時間、空間複雜度互換的設計思想
==》鄰接矩陣儲存起來比較浪費空間,但是使用起來比較節省時間。相反,鄰接表儲存起來比較節省空間,但是使用起來就比較耗時間。
訪問
eg:要確定,是否存在一條從頂點 2 到頂點 4 的邊,那我們就要遍歷頂點
==》連結串列儲存方法對快取不友好
==》沒有鄰接矩陣在查詢兩個頂點之間的關係時那麼高效。
改進:鄰接表同散列表一樣改進
在基於連結串列法解決衝突的散列表中,如果鏈過長,為了提高查詢效率,我們可以將連結串列換成其他更加高效的資料結構,比如平衡二叉查詢樹、平衡二叉樹、紅黑樹、跳錶、散列表或有序動態資料等等。
3、分析
儲存一個圖主要有兩種儲存方法
- 鄰接矩陣
- 鄰接表
對於社交網路(稀疏圖),使用鄰接矩陣儲存比較浪費儲存空間。==》採用鄰接表儲存
但是用一個鄰接表來儲存這種有向圖是不夠的。我們去查詢某個使用者關注了哪些使用者非常容易,但是如果要想知道某個使用者都被哪些使用者關注了,也就是使用者的粉絲列表,是非常困難的。
==》逆鄰接表
- 鄰接表中,每個頂點的連結串列中,儲存的就是這個頂點指向的頂點——如果要查詢某個使用者關注了哪些使用者,我們可以在鄰接表中查詢;
- 逆鄰接表中,每個頂點的連結串列中,儲存的是指向這個頂點的頂點。——如果要查詢某個使用者被哪些使用者關注了,我們從逆鄰接表中查詢。