数据结构与算法之数据结构 图扩展 带权图 / 有向无环图

数据结构与算法阿木 发布于 4 天前 2 次阅读


图扩展:带权图与有向无环图的数据结构与算法

图是数据结构中的一种重要类型,它由节点(也称为顶点)和边组成,用于表示实体之间的关系。在现实世界中,图广泛应用于网络、社交网络、交通系统等领域。本文将围绕带权图和有向无环图(DAG)这两种图的数据结构和算法进行探讨。

带权图

数据结构

带权图是一种特殊的图,其中每条边都有一个权重。在Python中,我们可以使用邻接表或邻接矩阵来表示带权图。

邻接表表示法

邻接表是一种使用链表来表示图的数据结构。对于带权图,我们可以使用一个字典来存储节点和与之相连的节点及其权重。

python

class WeightedGraph:


def __init__(self):


self.graph = {}

def add_edge(self, u, v, weight):


if u not in self.graph:


self.graph[u] = []


self.graph[u].append((v, weight))

def get_edges(self, u):


return self.graph.get(u, [])


邻接矩阵表示法

邻接矩阵是一个二维数组,其中矩阵的元素表示两个节点之间的权重。对于带权图,我们可以使用一个二维列表来表示邻接矩阵。

python

class WeightedGraph:


def __init__(self, vertices):


self.vertices = vertices


self.graph = [[0] vertices for _ in range(vertices)]

def add_edge(self, u, v, weight):


self.graph[u][v] = weight

def get_weight(self, u, v):


return self.graph[u][v]


算法

Dijkstra算法

Dijkstra算法用于找到图中两个节点之间的最短路径。它适用于带权图,并且边的权重都是非负的。

python

import heapq

def dijkstra(graph, start):


distances = {vertex: float('infinity') for vertex in graph}


distances[start] = 0


priority_queue = [(0, start)]

while priority_queue:


current_distance, current_vertex = heapq.heappop(priority_queue)

if current_distance > distances[current_vertex]:


continue

for neighbor, weight in graph[current_vertex]:


distance = current_distance + weight

if distance < distances[neighbor]:


distances[neighbor] = distance


heapq.heappush(priority_queue, (distance, neighbor))

return distances


Bellman-Ford算法

Bellman-Ford算法用于找到图中两个节点之间的最短路径,它适用于带权图,并且边的权重可以是负数。

python

def bellman_ford(graph, start):


distances = {vertex: float('infinity') for vertex in graph}


distances[start] = 0

for _ in range(len(graph) - 1):


for u in graph:


for v, weight in graph[u]:


if distances[u] + weight < distances[v]:


distances[v] = distances[u] + weight

检测负权重循环


for u in graph:


for v, weight in graph[u]:


if distances[u] + weight < distances[v]:


raise ValueError("Graph contains a negative-weight cycle")

return distances


有向无环图(DAG)

数据结构

有向无环图是一种没有环的有向图。在Python中,我们可以使用邻接表来表示DAG。

python

class DAG:


def __init__(self):


self.graph = {}

def add_edge(self, u, v):


if u not in self.graph:


self.graph[u] = []


self.graph[u].append(v)

def get_edges(self, u):


return self.graph.get(u, [])


算法

拓扑排序

拓扑排序是一种对有向无环图进行排序的方法,它确保了所有有向边都指向后续的节点。

python

def topological_sort(dag):


in_degree = {vertex: 0 for vertex in dag.graph}


for u in dag.graph:


for v in dag.graph[u]:


in_degree[v] += 1

queue = [vertex for vertex in dag.graph if in_degree[vertex] == 0]


sorted_list = []

while queue:


vertex = queue.pop(0)


sorted_list.append(vertex)


for v in dag.graph[vertex]:


in_degree[v] -= 1


if in_degree[v] == 0:


queue.append(v)

if len(sorted_list) == len(dag.graph):


return sorted_list


else:


raise ValueError("Graph has a cycle")


强连通分量

强连通分量是指在有向图中,任意两个节点之间都存在双向路径的子图。

python

def kosaraju(graph):


def dfs(v, visited, stack):


visited.add(v)


for i in graph[v]:


if i not in visited:


dfs(i, visited, stack)


stack.append(v)

def dfs2(v, visited, component):


visited.add(v)


component.append(v)


for i in graph2[v]:


if i not in visited:


dfs2(i, visited, component)

visited = set()


stack = []


graph2 = {v: [] for v in graph}


for v in graph:


for i in graph[v]:


graph2[i].append(v)

for v in graph:


if v not in visited:


dfs(v, visited, stack)

visited = set()


components = []


while stack:


v = stack.pop()


if v not in visited:


component = []


dfs2(v, visited, component)


components.append(component)

return components


总结

本文介绍了带权图和有向无环图(DAG)的数据结构和算法。带权图可以使用邻接表或邻接矩阵表示,并可以使用Dijkstra算法和Bellman-Ford算法来找到最短路径。有向无环图可以使用邻接表表示,并可以使用拓扑排序和Kosaraju算法来找到强连通分量。这些数据结构和算法在计算机科学和实际应用中都有广泛的应用。