1. 程式人生 > >十五、圖(graph)

十五、圖(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、分析

儲存一個圖主要有兩種儲存方法

  • 鄰接矩陣
  • 鄰接表

對於社交網路(稀疏圖),使用鄰接矩陣儲存比較浪費儲存空間。==》採用鄰接表儲存

但是用一個鄰接表來儲存這種有向圖是不夠的。我們去查詢某個使用者關注了哪些使用者非常容易,但是如果要想知道某個使用者都被哪些使用者關注了,也就是使用者的粉絲列表,是非常困難的。
==》逆鄰接表
在這裡插入圖片描述

  • 鄰接表中,每個頂點的連結串列中,儲存的就是這個頂點指向的頂點——如果要查詢某個使用者關注了哪些使用者,我們可以在鄰接表中查詢;
  • 逆鄰接表中,每個頂點的連結串列中,儲存的是指向這個頂點的頂點。——如果要查詢某個使用者被哪些使用者關注了,我們從逆鄰接表中查詢。