數據結構(八):鄰接表與鄰接矩陣

鄰接表和鄰接矩陣是圖的兩種常用存儲表示方式,用于記錄圖中任意兩個頂點之間的連通關系,包括權值。

對于圖 G=(V, E) 而言,其中 V 表示頂點集合,E 表示邊集合。

對于無向圖 graph,圖的頂點集合和邊集合如下:

V = \{1,2,3,4,5\}
E =\{(1,2),(1,3),(1,4),(2,3),(3,4),(3,5)\}

graph

對于有向圖 digraph,圖的頂點集合和邊集合如下:

V = \{1,2,3,4,5\}
E =\{<1,2>,<1,3>,<1,4>,<2,3>,<3,1>,<3,5>,<4,3>\}

digraph

鄰接表

無向圖 graph 表示

graph_adjacency_list

有向圖 digraph 表示

digraph_adjacency_list

若采用鄰接表表示,則需要申請 |V| 個列表,每個列表存儲一個頂點出發的所有相鄰頂點。如果圖 G 為有向圖,則 |V| 個列表存儲的總頂點個數為 |E|;如果圖 G 為無向圖,則 |V| 個列表存儲的總頂點個數為 2 |E|(暫不考慮自回路)。因為需要申請大小為 |V| 的數組來保存節點,對節點分配序號,所以需要申請大小為 |V| 的額外存儲空間,即鄰接表方式的存儲空間復雜度為 O(|V|+|E|)

鄰接矩陣

無向圖 graph 表示

graph_adjacency_matrix

有向圖 digraph 表示

digraph_adjacency_matrix

若采用鄰接矩陣表示,則需要申請空間大小為 |V|^2 的二維數組,在二位數組中保存每兩個頂點之間的連通關系,則無論有向圖或無向圖,鄰接矩陣方式的存儲空間復雜度皆為 O(|V|^2)。若只記錄圖中頂點是否連通,不記錄權值大小,則可以使用一個二進制位來表示二維數組的每個元素,并且根據無向圖的特點可知,無向圖的鄰接矩陣沿對角線對稱,所以可以選擇記錄一半鄰接矩陣的形式來節省空間開銷。

兩種存儲結構對比

根據鄰接表和鄰接矩陣的結構特性可知,當圖為稀疏圖、頂點較多,即圖結構比較大時,更適宜選擇鄰接表作為存儲結構。當圖為稠密圖、頂點較少時,或者不需要記錄圖中邊的權值時,使用鄰接矩陣作為存儲結構較為合適。

代碼附錄

鄰接表結構
# graph node definition
class Node(object):
    def __init__(self, index, weight, next = None):
        self.index = index
        self.weight = weight
        self.next = next

# adjacency list definition
class AdjacencyList(object):
    def __init__(self, number):
        self.number = number
        self.list = [None] * number

    # insert node
    def insert(self, origin, index, weight = 1):
        node = Node(index, weight, self.list[origin - 1])
        self.list[origin - 1] = node

測試代碼:

if __name__ == '__main__':
    graph = AdjacencyList(5)
    graph.insert(1, 2)
    graph.insert(1, 3)
    graph.insert(1, 4)
    graph.insert(2, 3)
    graph.insert(3, 1)
    graph.insert(3, 5)
    graph.insert(4, 3)
    for i in range(graph.number):
        print('node', (i + 1), 'links:', end = ' ')
        node = graph.list[i]
        while node:
            print(node.index, end = ' ')
            node = node.next
        print()

輸出結果:

node 1 links: 4 3 2 
node 2 links: 3 
node 3 links: 5 1 
node 4 links: 3 
node 5 links: 
鄰接矩陣結構
# adjacency list definition
class AdjacencyMatrix(object):
    def __init__(self, number):
        self.number = number
        self.list = [[None] * number for i in range(number)]

    # insert node
    def insert(self, origin, index, weight = 1):
        self.list[origin - 1][index - 1] = weight

測試代碼:

if __name__ == '__main__':
    graph = AdjacencyMatrix(5)
    graph.insert(1, 2)
    graph.insert(1, 3)
    graph.insert(1, 4)
    graph.insert(2, 3)
    graph.insert(3, 1)
    graph.insert(3, 5)
    graph.insert(4, 3)
    for i in range(graph.number):
        print('node', (i + 1), 'links:', end = ' ')
        j = 0
        while j < graph.number:
            print(j + 1, end = ' ') if graph.list[i][j] else None
            j += 1
        print()

輸出結果:

node 1 links: 2 3 4 
node 2 links: 3 
node 3 links: 1 5 
node 4 links: 3 
node 5 links: 

github 鏈接:鄰接表與鄰接矩陣

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容