数据结构7——图2
代码
例子
假设我们有一个社交网络,其中包含多个用户(节点)和他们之间的好友关系(边)。为了简化,我们考虑一个有向图,其中包含5个用户(A, B, C, D, E)和若干条好友关系边,每条边都带有权重,表示关系的紧密程度。具体的好友关系如下:
- A 是 B 的好友(权重为3)
- A 是 C 的好友(权重为5)
- B 是 C 的好友(权重为2)
- C 是 D 的好友(权重为4)
- D 是 E 的好友(权重为1)
- E 是 A 的好友(权重为6)
邻接矩阵表示
邻接矩阵是一个二维数组,用于表示图中顶点之间的连接关系。对于上述社交网络,其邻接矩阵可以表示如下(假设顶点按A, B, C, D, E的顺序排列):
A B C D E
A 0 3 5 0 0
B 0 0 2 0 0
C 0 0 0 4 0
D 0 0 0 0 1
E 6 0 0 0 0
在这个矩阵中,行表示起点,列表示终点,矩阵中的元素表示边的权重。如果两个顶点之间没有边,则对应位置为0(或某个表示无穷大的值,如+∞,但在实际编程中常用一个很大的数或特定的标记来表示)。
邻接表表示
邻接表是另一种表示图的方法,它通过链表的方式存储每个顶点的所有邻接点。对于上述社交网络,其邻接表可以表示如下:
A: 3->B, 5->C
B: 2->C
C: 4->D
D: 1->E
E: 6->A
在这个表示中,每个顶点后面跟着一个链表,链表中包含了从该顶点出发可以到达的所有顶点以及对应的边的权重。这种表示方法对于稀疏图来说非常有效,因为它只存储实际存在的边,而不像邻接矩阵那样需要为不存在的边也分配空间。
优缺点比较
-
邻接矩阵:
- 优点:实现简单,可以快速判断任意两个顶点之间是否存在边(时间复杂度为O(1))。
- 缺点:空间复杂度高,特别是对于稀疏图来说,会浪费大量空间来存储不存在的边。
-
邻接表:
- 优点:空间效率高,特别是对于稀疏图来说,可以大大节省存储空间。同时,添加和删除边的操作也比较灵活。
- 缺点:判断两个顶点之间是否存在边需要遍历链表,时间复杂度较高(最坏情况下为O(n),n为顶点的度数)。
。
代码
邻接矩阵表示
class GraphAdjacencyMatrix:
def __init__(self, num_vertices):
self.num_vertices = num_vertices
# 初始化邻接矩阵
self.adj_matrix = [[0] * num_vertices for _ in range(num_vertices)]
def add_edge(self, v1, v2):
# 无向图,设置两个方向的值
if v1 >= self.num_vertices or v2 >= self.num_vertices:
print("Error: Vertices out of range")
else:
self.adj_matrix[v1][v2] = 1
self.adj_matrix[v2][v1] = 1 # 注释此行表示有向图
def display(self):
for row in self.adj_matrix:
print(row)
# 创建图并添加边
num_vertices = 4
graph = GraphAdjacencyMatrix(num_vertices)
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(1, 3)
graph.display()
邻接表表示
class GraphAdjacencyList:
def __init__(self):
# 使用字典存储邻接表
self.adj_list = {}
def add_edge(self, v1, v2):
if v1 not in self.adj_list:
self.adj_list[v1] = []
if v2 not in self.adj_list:
self.adj_list[v2] = []
# 添加边(无向图,两边都要添加)
self.adj_list[v1].append(v2)
self.adj_list[v2].append(v1) # 注释此行表示有向图
def display(self):
for vertex, edges in self.adj_list.items():
print(f"{vertex}: {edges}")
# 创建图并添加边
graph = GraphAdjacencyList()
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(1, 3)
graph.display()
给矩阵建图
import networkx as nx
import matplotlib.pyplot as plt
def create_graph_from_adjacency_matrix(adj_matrix):
# 创建一个无向图
G = nx.Graph()
# 获取邻接矩阵的大小
num_vertices = len(adj_matrix)
# 添加顶点
for i in range(num_vertices):
G.add_node(i)
# 添加边
for i in range(num_vertices):
for j in range(i + 1, num_vertices): # 避免重复添加边
if adj_matrix[i][j] != 0: # 如果矩阵中有边(非零值),则添加边
G.add_edge(i, j)
return G
def draw_graph(G):
# 绘制图
pos = nx.spring_layout(G) # 节点布局
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=800, font_size=16, font_weight='bold', edge_color='gray')
plt.title('Graph Visualization')
plt.show()
# 示例邻接矩阵
adj_matrix = [
[0, 1, 1, 0],
[1, 0, 1, 1],
[1, 1, 0, 1],
[0, 1, 1, 0]
]
# 创建图并绘制
G = create_graph_from_adjacency_matrix(adj_matrix)
draw_graph(G)
给表建图
import networkx as nx
import matplotlib.pyplot as plt
def create_graph_from_adjacency_list(adj_list):
# 创建一个无向图
G = nx.Graph()
# 添加顶点和边
for node, neighbors in adj_list.items():
# 添加节点
G.add_node(node)
# 添加与当前节点相连的边
for neighbor in neighbors:
G.add_edge(node, neighbor)
return G
def draw_graph(G):
# 绘制图
pos = nx.spring_layout(G) # 节点布局
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=800, font_size=16, font_weight='bold', edge_color='gray')
plt.title('Graph Visualization')
plt.show()
# 示例邻接表
adj_list = {
0: [1, 2],
1: [0, 2, 3],
2: [0, 1],
3: [1]
}
# 创建图并绘制
G = create_graph_from_adjacency_list(adj_list)
draw_graph(G)
创建图
import networkx as nx
import matplotlib.pyplot as plt
# 创建一个无向图
G = nx.Graph()
# 添加边
G.add_edge(0, 1)
G.add_edge(0, 2)
G.add_edge(1, 2)
G.add_edge(1, 3)
# 绘制图
nx.draw(G, with_labels=True, node_color='lightblue', node_size=800, font_size=16)
plt.show()