feat:增加部分图论算法
This commit is contained in:
parent
1db70cdf59
commit
27a3402d1c
|
|
@ -12,4 +12,210 @@
|
||||||
|
|
||||||
### Bellman-Ford算法
|
### Bellman-Ford算法
|
||||||
|
|
||||||
### Bellman-Ford算法
|
#### 数学公式
|
||||||
|
|
||||||
|
对于图 $G=(V,E)$,Bellman-Ford算法通过迭代松弛更新每个顶点的最短路径估计:
|
||||||
|
|
||||||
|
$$d(v) = \min\{d(u) + w(u,v) | (u,v) \in E\}$$
|
||||||
|
|
||||||
|
其中:
|
||||||
|
- $d(v)$ 是从源顶点到顶点 $v$ 的最短路径估计
|
||||||
|
- $w(u,v)$ 是边 $(u,v)$ 的权重
|
||||||
|
- 迭代次数最多为 $|V|-1$ 次
|
||||||
|
|
||||||
|
#### Python实现
|
||||||
|
|
||||||
|
```python
|
||||||
|
def bellman_ford(graph, source):
|
||||||
|
"""
|
||||||
|
Bellman-Ford算法求单源最短路径
|
||||||
|
|
||||||
|
参数:
|
||||||
|
graph: 邻接表表示的图,格式 {u: [(v, w), ...]}
|
||||||
|
source: 源顶点
|
||||||
|
|
||||||
|
返回:
|
||||||
|
distances: 各顶点到源顶点的最短距离
|
||||||
|
"""
|
||||||
|
# 初始化距离
|
||||||
|
distances = {v: float('inf') for v in graph}
|
||||||
|
distances[source] = 0
|
||||||
|
|
||||||
|
# 获取所有顶点
|
||||||
|
vertices = list(graph.keys())
|
||||||
|
|
||||||
|
# 最多进行 |V|-1 次迭代
|
||||||
|
for _ in range(len(vertices) - 1):
|
||||||
|
# 对每条边进行松弛操作
|
||||||
|
for u in graph:
|
||||||
|
for v, w in graph[u]:
|
||||||
|
if distances[u] != float('inf') and distances[u] + w < distances[v]:
|
||||||
|
distances[v] = distances[u] + w
|
||||||
|
|
||||||
|
# 检测负权重环
|
||||||
|
for u in graph:
|
||||||
|
for v, w in graph[u]:
|
||||||
|
if distances[u] != float('inf') and distances[u] + w < distances[v]:
|
||||||
|
raise ValueError("图中存在负权重环")
|
||||||
|
|
||||||
|
return distances
|
||||||
|
|
||||||
|
|
||||||
|
# 示例使用
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 构建图 (邻接表)
|
||||||
|
graph = {
|
||||||
|
'A': [('B', 4), ('C', 2)],
|
||||||
|
'B': [('C', 3), ('D', 2), ('E', 3)],
|
||||||
|
'C': [('B', 1), ('D', 4)],
|
||||||
|
'D': [('E', -5)], # 负权重边
|
||||||
|
'E': []
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
distances = bellman_ford(graph, 'A')
|
||||||
|
print("Bellman-Ford 结果:", distances)
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常用算法Python实现
|
||||||
|
|
||||||
|
### 1. Dijkstra算法
|
||||||
|
|
||||||
|
#### 数学公式
|
||||||
|
|
||||||
|
Dijkstra算法维护一个优先队列,每次选取具有最小距离估计的顶点:
|
||||||
|
|
||||||
|
$$d(v) = \min_{u \in S} \{ d(u) + w(u,v) \}$$
|
||||||
|
|
||||||
|
其中 $S$ 是已确定最短路径的顶点集合。
|
||||||
|
|
||||||
|
#### Python实现
|
||||||
|
|
||||||
|
```python
|
||||||
|
import heapq
|
||||||
|
|
||||||
|
def dijkstra(graph, source):
|
||||||
|
"""
|
||||||
|
Dijkstra算法求单源最短路径
|
||||||
|
|
||||||
|
参数:
|
||||||
|
graph: 邻接表表示的图,格式 {u: [(v, w), ...]}
|
||||||
|
source: 源顶点
|
||||||
|
|
||||||
|
返回:
|
||||||
|
distances: 各顶点到源顶点的最短距离
|
||||||
|
"""
|
||||||
|
# 初始化距离
|
||||||
|
distances = {v: float('inf') for v in graph}
|
||||||
|
distances[source] = 0
|
||||||
|
|
||||||
|
# 优先队列: (距离, 顶点)
|
||||||
|
pq = [(0, source)]
|
||||||
|
visited = set()
|
||||||
|
|
||||||
|
while pq:
|
||||||
|
# 取出最小距离的顶点
|
||||||
|
current_dist, u = heapq.heappop(pq)
|
||||||
|
|
||||||
|
# 如果已访问则跳过
|
||||||
|
if u in visited:
|
||||||
|
continue
|
||||||
|
visited.add(u)
|
||||||
|
|
||||||
|
# 更新邻接顶点的距离
|
||||||
|
for v, w in graph.get(u, []):
|
||||||
|
if v not in visited and current_dist + w < distances[v]:
|
||||||
|
distances[v] = current_dist + w
|
||||||
|
heapq.heappush(pq, (distances[v], v))
|
||||||
|
|
||||||
|
return distances
|
||||||
|
|
||||||
|
|
||||||
|
# 示例使用
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 构建图 (邻接表)
|
||||||
|
graph = {
|
||||||
|
'A': [('B', 4), ('C', 2)],
|
||||||
|
'B': [('C', 3), ('D', 2), ('E', 3)],
|
||||||
|
'C': [('B', 1), ('D', 4)],
|
||||||
|
'D': [('E', 5)],
|
||||||
|
'E': []
|
||||||
|
}
|
||||||
|
|
||||||
|
distances = dijkstra(graph, 'A')
|
||||||
|
print("Dijkstra 结果:", distances)
|
||||||
|
# 输出: {'A': 0, 'B': 3, 'C': 2, 'D': 5, 'E': 8}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Bellman-Ford算法
|
||||||
|
|
||||||
|
#### 数学公式
|
||||||
|
|
||||||
|
对于图 $G=(V,E)$,Bellman-Ford算法通过迭代松弛更新每个顶点的最短路径估计:
|
||||||
|
|
||||||
|
$$d(v) = \min\{d(u) + w(u,v) | (u,v) \in E\}$$
|
||||||
|
|
||||||
|
其中:
|
||||||
|
- $d(v)$ 是从源顶点到顶点 $v$ 的最短路径估计
|
||||||
|
- $w(u,v)$ 是边 $(u,v)$ 的权重
|
||||||
|
- 迭代次数最多为 $|V|-1$ 次
|
||||||
|
|
||||||
|
#### Python实现
|
||||||
|
|
||||||
|
```python
|
||||||
|
def bellman_ford(graph, source):
|
||||||
|
"""
|
||||||
|
Bellman-Ford算法求单源最短路径
|
||||||
|
|
||||||
|
参数:
|
||||||
|
graph: 邻接表表示的图,格式 {u: [(v, w), ...]}
|
||||||
|
source: 源顶点
|
||||||
|
|
||||||
|
返回:
|
||||||
|
distances: 各顶点到源顶点的最短距离
|
||||||
|
"""
|
||||||
|
# 初始化距离
|
||||||
|
distances = {v: float('inf') for v in graph}
|
||||||
|
distances[source] = 0
|
||||||
|
|
||||||
|
# 获取所有顶点
|
||||||
|
vertices = list(graph.keys())
|
||||||
|
|
||||||
|
# 最多进行 |V|-1 次迭代
|
||||||
|
for _ in range(len(vertices) - 1):
|
||||||
|
# 对每条边进行松弛操作
|
||||||
|
for u in graph:
|
||||||
|
for v, w in graph[u]:
|
||||||
|
if distances[u] != float('inf') and distances[u] + w < distances[v]:
|
||||||
|
distances[v] = distances[u] + w
|
||||||
|
|
||||||
|
# 检测负权重环
|
||||||
|
for u in graph:
|
||||||
|
for v, w in graph[u]:
|
||||||
|
if distances[u] != float('inf') and distances[u] + w < distances[v]:
|
||||||
|
raise ValueError("图中存在负权重环")
|
||||||
|
|
||||||
|
return distances
|
||||||
|
|
||||||
|
|
||||||
|
# 示例使用
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 构建图 (邻接表)
|
||||||
|
graph = {
|
||||||
|
'A': [('B', 4), ('C', 2)],
|
||||||
|
'B': [('C', 3), ('D', 2), ('E', 3)],
|
||||||
|
'C': [('B', 1), ('D', 4)],
|
||||||
|
'D': [('E', -5)], # 负权重边
|
||||||
|
'E': []
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
distances = bellman_ford(graph, 'A')
|
||||||
|
print("Bellman-Ford 结果:", distances)
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
```
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue