python无向图最短路径_Dijkstra算法python的实现(有向图/无向图)

本文介绍了如何使用Dijkstra算法解决无环有向图和无向图的最短路径问题。通过创建Edge、Graph、MinPQ和ShortestPath四个类,实现了最小优先队列和Dijkstra算法的主要功能,包括添加边、获取相邻顶点、找到最短路径等操作。此外,还提供了测试用例展示如何找到给定图中两点间的最短路径。
摘要由CSDN通过智能技术生成

我用Dijkstra算法,写了一个无环有向图/无向图(多加一条相反的路径仅此而已) 的最短路径问题的解决方案。如果是无向图也很简单,把每个无向的edge拆开成两个有向的就可以解决了。

为了每次弹出正确的端点,我也实现了一个最小优先队列。

代码由4个类构成:

Edge定义两个端点之间路径,有三个属性:源,目的地和权重。

Graph定义了整个图形,包括路径和端点。在这个code里面,端点不能单独添加。当添加路径的时候,端点会自动添加。

MinPQ定义一个优先队列,它用来储存端点到起始点的最小距离。它有一个方法del_min,用来弹出队列中距离最小的那个端点。

ShortestPath是主要类,它使用Dijkstra算法,有两个方法:

path_to(vertex)方法返回包含从起点到顶点的最短路径的list 。

main(list_Grph,from_point,to_point) //该方法主要构造 并且输出最短路径经过的节点

list_Grph 使所有边的一个list 下面有例子可以看看

from_point //从哪一个节点出发

to_point //到哪个节点

dist_to(vertex)返回path_to(vertex)的总长度。

class Edge:

def __init__(self, source, destine, weight):

self.weight = weight

self.source = source

self.destine = destine

class Graph:

def __init__(self):

self.vertices = set([])

self.edges = set([])

self.adjacents = {}

def add_edge(self, edge):

self.vertices.add(edge.source)

self.vertices.add(edge.destine)

if edge.source not in self.adjacents.keys():

self.adjacents[edge.source] = set([])

self.adjacents[edge.source].add(edge)

self.edges.add(edge)

# print("add edge from {} to {}, weight {}".format(edge.source, edge.destine, edge.weight))

def get_adjacents(self, vertex):

# print("get the adjacent vertices of vertex {}".format(vertex))

if vertex not in self.adjacents.keys():

return set([])

return self.adjacents[vertex]

def vertex_number(self):

return len(self.vertices)

def edge_number(self):

return len(self.edges)

class MinPQ:

def __init__(self):

self.queue = [(0, 0)]

# print("create a min Priority Queue to record the distance")

def is_empty(self):

return len(self.queue) == 1

def size(self):

return len(self.queue) - 1

def min(self):

return self.queue[1]

def insert(self, vertex, new_value):

self.queue.append((vertex, new_value))

self.swim(self.size())

def del_min(self):

self.queue[1], self.queue[-1] = self.queue[-1], self.queue[1]

temp = self.queue.pop(-1)

self.sink(1)

return temp

def swim(self, index):

while index > 1 and self.queue[index // 2][1] > self.queue[index][1]:

self.queue[index //

2], self.queue[index] = self.queue[index], self.queue[

index // 2]

index = index // 2

def sink(self, index):

while 2 * index <= self.size():

next_level = 2 * index

if next_level < self.size() and self.queue[next_level][

1] > self.queue[next_level + 1][1]:

next_level += 1

if self.queue[index][1] <= self.queue[next_level][1]:

return

self.queue[index], self.queue[next_level] = self.queue[

next_level], self.queue[index]

index = next_level

def contains(self, vertex):

for index in range(1, len(self.queue)):

if self.queue[index][0] == vertex:

return True

return False

def change_dist(self, vertex, new_dist):

for index in range(1, len(self.queue)):

if self.queue[index][0] == vertex:

self.queue[index] = (vertex, new_dist)

class ShortestPath:

def __init__(self, graph, start_point):

self.dist_to = {}

self.edge_to = {}

for vertex in graph.vertices:

self.dist_to[vertex] = float("inf")

self.dist_to[start_point] = start_point

self.start_point = start_point

self.dist_queue = MinPQ()

self.dist_queue.insert(start_point, self.dist_to[start_point])

# print("insert the start point into the priority queue and initialize the distance")

while not self.dist_queue.is_empty():

vertex, _ = self.dist_queue.del_min()

# print("grow the mini-distance tree by poping vertex {} from the queue".format(vertex))

for edge in graph.get_adjacents(vertex):

self.relax(edge)

def relax(self, edge):

# print("relax edge from {} to {}".format(edge.source, edge.destine))

source = edge.source

destine = edge.destine

if self.dist_to[destine] > self.dist_to[source] + edge.weight:

self.dist_to[destine] = self.dist_to[source] + edge.weight

self.edge_to[destine] = edge

if self.dist_queue.contains(destine):

self.dist_queue.change_dist(destine, self.dist_to[destine])

else:

self.dist_queue.insert(destine, self.dist_to[destine])

def dist_to(self, vertex):

return self.dist_to[vertex]

def path_to(self, vertex):

lPath = [vertex]

temp_vertex = vertex

while temp_vertex != self.start_point:

temp_vertex = self.edge_to[temp_vertex].source

lPath.append(temp_vertex)

lPath.reverse()

return lPath

def main(list_Grph,from_point,to_point):

test = Graph()

#Create an graph

for item in list_Grph:

test.add_edge(Edge(item[0], item[1],item[2]))

# you will need to the next line of code if the graph is a disorderly

#test.add_edge(Edge(item[1], item[0],item[2]))

path = ShortestPath(test, from_point)

distPath = path.path_to(to_point);

print "the distPth is :"

print distPath

def test():

edge_1=[1,2,1]

edge_2=[2,5,1]

edge_3=[2,4,1]

edge_4=[2,3,2]

edge_5=[3,4,1]

edge_6=[3,6,2]

edge_7=[4,6,1]

list_edge =[edge_1,edge_2,edge_3,edge_4,edge_5,edge_6,edge_7]

main(list_edge,5,6)

test()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值