十五、图(graph)
引入
社交網絡,如何存儲微博、微信等這些社交網絡的好友關系?
==》圖
一、圖(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 的邊,那我們就要遍歷頂點 2 對應的那條鏈表,看鏈表中是否存在頂點 4。
==》鏈表存儲方法對緩存不友好
==》沒有鄰接矩陣在查詢兩個頂點之間的關系時那么高效。
改進:鄰接表同散列表一樣改進
在基于鏈表法解決沖突的散列表中,如果鏈過長,為了提高查找效率,我們可以將鏈表換成其他更加高效的數據結構,比如平衡二叉查找樹、平衡二叉樹、紅黑樹、跳表、散列表或有序動態數據等等。
3、分析
存儲一個圖主要有兩種存儲方法
- 鄰接矩陣
- 鄰接表
對于社交網絡(稀疏圖),使用鄰接矩陣存儲比較浪費存儲空間。==》采用鄰接表存儲
但是用一個鄰接表來存儲這種有向圖是不夠的。我們去查找某個用戶關注了哪些用戶非常容易,但是如果要想知道某個用戶都被哪些用戶關注了,也就是用戶的粉絲列表,是非常困難的。
==》逆鄰接表
- 鄰接表中,每個頂點的鏈表中,存儲的就是這個頂點指向的頂點——如果要查找某個用戶關注了哪些用戶,我們可以在鄰接表中查找;
- 逆鄰接表中,每個頂點的鏈表中,存儲的是指向這個頂點的頂點。——如果要查找某個用戶被哪些用戶關注了,我們從逆鄰接表中查找。
問題:上述的鄰接表不適合快速判斷兩個用戶之間是否是關注與被關注的關系。
==》將鄰接表中的鏈表改為支持快速查找的動態數據結構:紅黑樹、跳表、有序動態數組或散列表 + 哈希算法。
總結
以上是生活随笔為你收集整理的十五、图(graph)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 十四、堆(Heap)
- 下一篇: 【LeetCode】1. Two Sum