鄰接表和鄰接矩陣是圖的兩種常用存儲表示方式,用于記錄圖中任意兩個頂點之間的連通關系,包括權值。
對于圖
而言,其中
表示頂點集合,
表示邊集合。
對于無向圖 graph,圖的頂點集合和邊集合如下:
graph
對于有向圖 digraph,圖的頂點集合和邊集合如下:
digraph
鄰接表
無向圖 graph 表示
graph_adjacency_list
有向圖 digraph 表示
digraph_adjacency_list
若采用鄰接表表示,則需要申請 個列表,每個列表存儲一個頂點出發的所有相鄰頂點。如果圖
為有向圖,則
個列表存儲的總頂點個數為
;如果圖
為無向圖,則
個列表存儲的總頂點個數為
(暫不考慮自回路)。因為需要申請大小為
的數組來保存節點,對節點分配序號,所以需要申請大小為
的額外存儲空間,即鄰接表方式的存儲空間復雜度為
。
鄰接矩陣
無向圖 graph 表示
graph_adjacency_matrix
有向圖 digraph 表示
digraph_adjacency_matrix
若采用鄰接矩陣表示,則需要申請空間大小為 的二維數組,在二位數組中保存每兩個頂點之間的連通關系,則無論有向圖或無向圖,鄰接矩陣方式的存儲空間復雜度皆為
。若只記錄圖中頂點是否連通,不記錄權值大小,則可以使用一個二進制位來表示二維數組的每個元素,并且根據無向圖的特點可知,無向圖的鄰接矩陣沿對角線對稱,所以可以選擇記錄一半鄰接矩陣的形式來節省空間開銷。
兩種存儲結構對比
根據鄰接表和鄰接矩陣的結構特性可知,當圖為稀疏圖、頂點較多,即圖結構比較大時,更適宜選擇鄰接表作為存儲結構。當圖為稠密圖、頂點較少時,或者不需要記錄圖中邊的權值時,使用鄰接矩陣作為存儲結構較為合適。
代碼附錄
鄰接表結構
# 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
鏈接:鄰接表與鄰接矩陣