from queue import Queue
import sys
class DirectedGraph:
def __init__(self, num_vertices):
self.num_vertices = num_vertices
self.adj_matrix = [[0] * num_vertices for _ in range(num_vertices)]
self.adj_list = [[] for _ in range(num_vertices)]
def add_edge(self, start_vertex, end_vertex, weight=1):
if 0 <= start_vertex < self.num_vertices and 0 <= end_vertex < self.num_vertices:
self.adj_matrix[start_vertex][end_vertex] = weight
self.adj_list[start_vertex].append((end_vertex, weight))
def remove_edge(self, start_vertex, end_vertex):
if 0 <= start_vertex < self.num_vertices and 0 <= end_vertex < self.num_vertices:
self.adj_matrix[start_vertex][end_vertex] = 0
self.adj_list[start_vertex] = [(v, w) for v, w in self.adj_list[start_vertex] if v != end_vertex]
@classmethod
def from_adjacency_matrix(cls, adj_matrix):
num_vertices = len(adj_matrix)
graph = cls(num_vertices)
for i in range(num_vertices):
for j in range(num_vertices):
weight = adj_matrix[i][j]
if weight != 0:
graph.add_edge(i, j, weight)
return graph
@classmethod
def from_adjacency_list(cls, adj_list):
num_vertices = len(adj_list)
graph = cls(num_vertices)
for start_vertex, neighbors in enumerate(adj_list):
for end_vertex, weight in neighbors:
graph.add_edge(start_vertex, end_vertex, weight)
return graph
class UndirectedGraph:
def __init__(self, num_vertices):
self.num_vertices = num_vertices
self.adj_matrix = [[0] * num_vertices for _ in range(num_vertices)]
self.adj_list = [[] for _ in range(num_vertices)]
def add_edge(self, vertex1, vertex2, weight=1):
if vertex1 >= 0 and vertex1 < self.num_vertices and vertex2 >= 0 and vertex2 < self.num_vertices:
self.adj_matrix[vertex1][vertex2] = weight
self.adj_matrix[vertex2][vertex1] = weight
self.adj_list[vertex1].append((vertex2, weight))
self.adj_list[vertex2].append((vertex1, weight))
def remove_edge(self, vertex1, vertex2):
if 0 <= vertex1 < self.num_vertices and 0 <= vertex2 < self.num_vertices:
self.adj_matrix[vertex1][vertex2] = 0
self.adj_matrix[vertex2][vertex1] = 0
self.adj_list[vertex1] = [(v, w) for v, w in self.adj_list[vertex1] if v != vertex2]
self.adj_list[vertex2] = [(v, w) for v, w in self.adj_list[vertex2] if v != vertex1]
def depth_first_traversal(self, start_vertex):
visited = [False] * self.num_vertices
self._depth_first_traversal_recursive(start_vertex, visited)
def _depth_first_traversal_recursive(self, vertex, visited):
visited[vertex] = True
print(vertex, end=" ")
for neighbor, _ in self.adj_list[vertex]:
if not visited[neighbor]:
self._depth_first_traversal_recursive(neighbor, visited)
def breadth_first_traversal(self, start_vertex):
visited = [False] * self.num_vertices
queue = Queue()
visited[start_vertex] = True
queue.put(start_vertex)
while not queue.empty():
vertex = queue.get()
print(vertex, end=" ")
for neighbor, _ in self.adj_list[vertex]:
if not visited[neighbor]:
visited[neighbor] = True
queue.put(neighbor)
@classmethod
def from_adjacency_matrix(cls, adj_matrix):
num_vertices = len(adj_matrix)
graph = cls(num_vertices)
for i in range(num_vertices):
for j in range(i, num_vertices):
weight = adj_matrix[i][j]
if weight != 0:
graph.add_edge(i, j, weight)
return graph
def minimum_spanning_tree(self):
visited = [False] * self.num_vertices
key = [sys.maxsize] * self.num_vertices
parent = [None] * self.num_vertices
key[0] = 0 # Choose the first vertex as the starting point
for _ in range(self.num_vertices):
u = self._min_key_vertex(key, visited)
visited[u] = True
for v, weight in self.adj_list[u]:
if not visited[v] and weight < key[v]:
key[v] = weight
parent[v] = u
mst_adj_list = [[] for _ in range(self.num_vertices)]
for v in range(1, self.num_vertices):
u = parent[v]
weight = key[v]
mst_adj_list[u].append((v, weight))
mst_adj_list[v].append((u, weight))
mst = UndirectedGraph(self.num_vertices)
mst.adj_list = mst_adj_list
return mst
def _min_key_vertex(self, key, visited):
min_key = sys.maxsize
min_vertex = -1
for v in range(self.num_vertices):
if not visited[v] and key[v] < min_key:
min_key = key[v]
min_vertex = v
return min_vertex
if __name__ == '__main__':
# 从邻接表建立有向图
adj_list = [
[(1, 5), (2, 4)],
[(3, 7), (4, 5)],
[(3, 3), (4, 6)],
[(5, 5)],
[(5, 3)],
[]
]
directed_graph = DirectedGraph.from_adjacency_list(adj_list)
# 从邻接矩阵建立有向图
adj_matrix = [
[0, 5, 4, 0, 0, 0],
[0, 0, 0, 7, 5, 0],
[0, 0, 0, 3, 6, 0],
[0, 0, 0, 0, 0, 5],
[0, 0, 0, 0, 0, 3],
[0, 0, 0, 0, 0, 0]
]
directed_graph2 = DirectedGraph.from_adjacency_matrix(adj_matrix)
# 打印有向图的邻接矩阵和邻接表
print("有向图邻接矩阵:")
for row in directed_graph.adj_matrix:
print(row)
print("有向图邻接表:")
for i, vertex in enumerate(directed_graph.adj_list):
print(f"Vertex {i}: {vertex}")
# 建立无向图
undirected_graph = UndirectedGraph.from_adjacency_matrix(adj_matrix)
# 打印无向图的邻接矩阵和邻接表
print("无向图邻接矩阵:")
for row in undirected_graph.adj_matrix:
print(row)
print("深度优先遍历:")
undirected_graph.depth_first_traversal(0)
print("\n广度优先遍历:")
undirected_graph.breadth_first_traversal(0)
mst = undirected_graph.minimum_spanning_tree()
print("\n最小生成树的邻接表:")
for i, vertex in enumerate(mst.adj_list):
print(f"Vertex {i}: {vertex}")
python无向图有向图基本操作
最新推荐文章于 2024-05-18 08:44:25 发布