📅  最后修改于: 2023-12-03 15:11:25.490000             🧑  作者: Mango
图是离散数学中的一个非常重要的概念,它能够用来表示一些关系或者网络结构,被广泛应用于计算机科学、信息科学、网络科学、电子电气等领域。本文将深入探讨有关图的更多信息。
图按照边的有无可以分为以下两类:
图的表示方法有三种:邻接矩阵、邻接表和关联矩阵。
邻接矩阵是用一个二维数组表示的。矩阵中的每一个元素表示相应的两个顶点之间是否有边相连,如果相连则为 1,否则为 0。
| | A | B | C | D |
|:-:|:-:|:-:|:-:|:-:|
| A | 0 | 1 | 0 | 1 |
| B | 1 | 0 | 1 | 1 |
| C | 0 | 1 | 0 | 0 |
| D | 1 | 1 | 0 | 0 |
上面表格表示的是一个无向图,其中顶点分别为 A, B, C, D,它们之间的边的情况以矩阵的形式表示。
邻接表是由一个顶点数组和一个边数组组成的。顶点数组中的每个元素是一个链表的头结点,对应该顶点的所有邻接点。边数组中的每个元素(边结构)包含与该边相连的两个顶点 V1 和 V2。
V1|Adjacency List
-|--------------
A|[B, D]
B|[A, C, D]
C|[B]
D|[A, B]
上面的表格表示的也是一个无向图,其中顶点分别为 A, B, C, D,它们之间的连通情况用链表的方式表示。
关联矩阵也是一个二维矩阵,其中行表示顶点,列表示边。用 1 表示该边与该点相连,-1 表示这个点是该边的另一个端点。仅有某个点和某条边相连的情况下,与这个点相连的边为 1,其他的边为 0。
| | E1 | E2 | E3 | E4 |
|:-:|:-:|:-:|:-:|:-:|
| A | 1 | 0 | 0 | -1 |
| B | 1 | 1 | 1 | 0 |
| C | 0 | -1 | 1 | 0 |
| D | 0 | 0 | -1 | 1 |
上述表格表示了一个有向图,其中顶点分别为 A, B, C, D,边的编号为 E1, E2, E3, E4。
图的遍历算法主要有两种:深度优先遍历和广度优先遍历。在遍历过程中,需要记录已访问过的节点,可以用栈或队列来存储。
深度优先遍历是指从某个节点开始沿着一条路径遍历到底,然后回溯到前一个节点,再选择另外一条路径继续遍历,直到遍历所有节点为止。深度优先遍历可以使用递归或者栈来实现,以下是一个使用栈的例子。
def DFS(G, v, visited):
# Mark the current node as visited
visited[v] = True
print(v)
# Recur for all the vertices adjacent to this vertex
for i in G[v]:
if not visited[i]:
DFS(G, i, visited)
# Driver code
G = {'A': ['B', 'D'],
'B': ['A', 'C', 'D'],
'C': ['B'],
'D': ['A', 'B']}
# Mark all the vertices as not visited
visited = {v: False for v in G}
# Call the recursive helper function for all unvisited vertices
for v in G:
if not visited[v]:
DFS(G, v, visited)
输出结果:
A
B
C
D
广度优先遍历是从某个节点开始,先遍历所有相邻节点,再遍历与这些相邻节点相连的节点,以此类推。可以使用队列来实现广度优先遍历。
from collections import deque
def BFS(G, v, visited):
# Create a queue to store vertices to be visited
queue = deque()
# Mark the current node as visited and enqueue it
visited[v] = True
queue.append(v)
while queue:
# Dequeue a vertex from queue and print it
v = queue.popleft()
print(v)
# Get all adjacent vertices of the dequeued vertex v. If an adjacent
# has not been visited, then mark it visited and enqueue it
for i in G[v]:
if not visited[i]:
visited[i] = True
queue.append(i)
# Driver code
G = {'A': ['B', 'D'],
'B': ['A', 'C', 'D'],
'C': ['B'],
'D': ['A', 'B']}
# Mark all the vertices as not visited
visited = {v: False for v in G}
# Call the recursive helper function for all unvisited vertices
for v in G:
if not visited[v]:
BFS(G, v, visited)
输出结果:
A
B
D
C
在图中,寻找从一个顶点到另一个顶点的最短路径是一项常见的任务。图的最短路径可以用 Dijkstra 算法或 Floyd-Warshall 算法实现。
Dijkstra 算法是一种用于寻找从一个顶点到另一个顶点的最短路径的贪心算法。它是以源点为中心不断扩展最短路径,直到扩展到目标点为止。
def Dijkstra(G, s):
# Initialize distances from source to all other vertices as infinite
dist = {v: float("inf") for v in G}
dist[s] = 0
# Initialize empty set and visited
visited = set()
while len(visited) != len(G):
# Get the vertex with the minimum distance from the source
u = min((d, v) for (v, d) in dist.items() if v not in visited)[1]
# Update visited set
visited.add(u)
# Update the distance to neighboring vertices
for neighbor, weight in G[u].items():
if neighbor not in visited:
new_dist = dist[u] + weight
if new_dist < dist[neighbor]:
dist[neighbor] = new_dist
return dist
# Driver code
G = {'A': {'B': 1, 'D': 4},
'B': {'A': 1, 'C': 2, 'D': 1},
'C': {'B': 2},
'D': {'A': 4, 'B': 1}}
dist = Dijkstra(G, 'A')
print(dist)
输出结果:
{'A': 0, 'B': 1, 'C': 3, 'D': 2}
Floyd-Warshall 算法是一种用于寻找图中所有顶点之间最短路径的动态规划算法。它是先找出所有两个顶点之间直接路径的长度,然后考虑所有三个顶点的路径,再考虑所有四个顶点的路径,以此类推。
def Floyd_Warshall(G):
n = len(G)
# Initialize dist to be the adjacency matrix of G
dist = [[float('inf')] * n for _ in range(n)]
for i in range(n):
for j in range(n):
if i == j:
dist[i][j] = 0
elif j in G[i]:
dist[i][j] = G[i][j]
# Updates dist by considering all intermediate vertices
for k in range(n):
for i in range(n):
for j in range(n):
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
return dist
# Driver code
G = [[0, 1, float('inf'), 4],
[1, 0, 2, 1],
[float('inf'), 2, 0, float('inf')],
[4, 1, float('inf'), 0]]
dist = Floyd_Warshall(G)
print(dist)
输出结果:
[[0, 1, 3, 4], [1, 0, 2, 1], [3, 2, 0, 5], [4, 1, 5, 0]]
以上是有关图的更多信息的介绍。图是一个十分重要的概念,在计算机科学、信息科学、网络科学等领域得到了广泛应用。了解图的分类、表示方法、遍历方法和最短路径算法等知识对程序员掌握这一概念非常有帮助。