python实现Dijkstra算法

下面是用python实现Dijkstra算法的代码:

# -*- coding: utf-8 -*-
"""
Created on Fri Jul 07 11:33:19 2017

@author: linzr
"""
## 表示无穷大
INF_val = 9999

class Dijkstra_Path():
    def __init__(self, node_map):
        self.node_map = node_map
        self.node_length = len(node_map)
        self.used_node_list = []
        self.collected_node_dict = {}
    
    def __call__(self, from_node, to_node):
        self.from_node = from_node
        self.to_node = to_node
        self._init_dijkstra()
        return self._format_path()

    def _init_dijkstra(self):
        ## Add from_node to used_node_list
        self.used_node_list.append(self.from_node)
        for index1 in range(self.node_length):
            self.collected_node_dict[index1] = [INF_val, -1]
  
        self.collected_node_dict[self.from_node] = [0, -1] # from_node don't have pre_node
        for index1, weight_val in enumerate(self.node_map[self.from_node]):
            if weight_val:
                self.collected_node_dict[index1] = [weight_val, self.from_node] # [weight_val, pre_node]
        
        self._foreach_dijkstra()
    
    def _foreach_dijkstra(self):
        while(len(self.used_node_list) < self.node_length - 1):
            min_key = -1
            min_val = INF_val
            for key, val in self.collected_node_dict.items(): # 遍历已有权值节点
                if val[0] < min_val and key not in self.used_node_list:
                    min_key = key
                    min_val = val[0]

            ## 把最小的值加入到used_node_list        
            if min_key != -1:
                self.used_node_list.append(min_key)

            for index1, weight_val in enumerate(self.node_map[min_key]):
                ## 对刚加入到used_node_list中的节点的相邻点进行遍历比较
                if weight_val > 0 and self.collected_node_dict[index1][0] > weight_val + min_val:
                    self.collected_node_dict[index1][0] = weight_val + min_val # update weight_val
                    self.collected_node_dict[index1][1] = min_key


    def _format_path(self):
        node_list = []
        temp_node = self.to_node
        node_list.append((temp_node, self.collected_node_dict[temp_node][0]))
        while self.collected_node_dict[temp_node][1] != -1:
          temp_node = self.collected_node_dict[temp_node][1]
          node_list.append((temp_node, self.collected_node_dict[temp_node][0]))
        node_list.reverse()
        return node_list

def set_node_map(node_map, node, node_list):
    for x, y, val in node_list:
        node_map[node.index(x)][node.index(y)] = node_map[node.index(y)][node.index(x)] = val

    
if __name__ == "__main__":
    node = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    node_list = [('A', 'F', 9), ('A', 'B', 10), ('A', 'G', 15), ('B', 'F', 2),
                 ('G', 'F', 3), ('G', 'E', 12), ('G', 'C', 10), ('C', 'E', 1),
                 ('E', 'D', 7)]
  
    ## init node_map to 0
    node_map = [[0 for val in xrange(len(node))] for val in xrange(len(node))]
  
    ## set node_map
    set_node_map(node_map, node, node_list)
  
    ## select one node to obj node, e.g. A --> D(node[0] --> node[3])
    from_node = node.index('A')
    to_node = node.index('E')
    dijkstrapath = Dijkstra_Path(node_map)
    path = dijkstrapath(from_node, to_node)
    print path

网络拓扑图如下:


运行结果为[(0, 0), (5, 9), (6, 12), (2, 22), (4, 23)]

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 当然可以,以下是Dijkstra算法Python代码: ```python import heapq def dijkstra(graph, start): # 初始化距离和前驱字典 distances = {vertex: float('inf') for vertex in graph} distances[start] = 0 previous_vertices = {vertex: None for vertex in graph} # 初始化堆 vertices = [(0, start)] heapq.heapify(vertices) while vertices: # 取出堆中最小距离的节点 current_distance, current_vertex = heapq.heappop(vertices) # 如果当前距离已经大于记录的距离,则直接跳过 if current_distance > distances[current_vertex]: continue # 遍历当前节点的所有邻居 for neighbor, weight in graph[current_vertex].items(): distance = current_distance + weight # 如果新距离比记录距离小,则更新 if distance < distances[neighbor]: distances[neighbor] = distance previous_vertices[neighbor] = current_vertex heapq.heappush(vertices, (distance, neighbor)) return distances, previous_vertices ``` 以上代码实现Dijkstra算法,接受一个邻接字典表示的图和一个起始节点,返回一个距离字典和前驱字典。其中,邻接字典中每个键值对表示一个节点和它的所有邻居及边权重。 ### 回答2: Dijkstra算法(又称为迪杰斯特拉算法、戴克斯特拉算法)是一种用于计算图中最短路径的贪心算法,广泛应用于路由算法或作为其他图算法的子模块。Dijkstra算法本质上是一种贪心算法,每次找到到某个节点最短路径上的下一个节点,并标记出该节点到起点的距离,推广到整个图上就得到了从起点到各个节点的最短路径。 下面给出Dijkstra算法Python代码实现: ``` import heapq def dijkstra(graph, start): distances = {vertex: 0 if vertex == start else float('inf') for vertex in graph} heap = [(0, start)] while heap: current_distance, current_vertex = heapq.heappop(heap) if current_distance > distances[current_vertex]: continue for neighbor, weight in graph[current_vertex].items(): distance = current_distance + weight if distance < distances[neighbor]: distances[neighbor] = distance heapq.heappush(heap, (distance, neighbor)) return distances ``` 这个算法首先初始化了每个节点到起点的距离,然后将起点加入堆中,堆中存放的是当前最短路径节点和对应的距离。然后每次从堆中取出堆顶元素,如果堆顶元素的距离已经大于当前最短距离,则跳过该节点。如果堆顶元素的距离小于当前最短距离,则更新该节点到起点的距离,并将它的邻居节点加入堆中。 这个实现中使用了一个优先队列来维护最短距离的节点,这使得算法的时间复杂度从O(n^2)降低到了O(m log n),其中n是节点数,m是边数。 ### 回答3: Dijkstra算法是一种用于寻找带权有向图中单源最短路径的算法。本文将为大家介绍如何用Python语言实现Dijkstra算法Dijkstra算法主要思路是通过贪心策略,先找到起点到每个顶点的最短路径,然后利用这些信息进一步缩小搜索范围,最终找到起点到目标点的最短路径。 以下是Dijkstra算法Python代码实现: ``` python #定义初始化函数,将各个点的距离和前一个节点都初始化为-1 def init(graph, start): d = {} p = {} for node in graph: d[node] = -1 p[node] = "" d[start] = 0 return d, p #定义算法函数。其中graph为图的数据表示(例如邻接矩阵或邻接表),start是起始节点 def dijkstra(graph, start): d, p = init(graph, start) unseen_nodes = list(graph.keys()) #未处理的节点集合 while len(unseen_nodes) > 0: #找到当前未处理节点中距离起点最短的节点 shortest = None node = "" for temp_node in unseen_nodes: if shortest == None: shortest = d[temp_node] node = temp_node elif d[temp_node] < shortest: shortest = d[temp_node] node = temp_node #遍历当前节点的所有出边,更新相邻节点的距离和前一个节点 for i, weight in graph[node].items(): if d[i] < 0 or d[i] > d[node] + weight: d[i] = d[node] + weight p[i] = node unseen_nodes.remove(node) return d, p #测试代码 graph = {0: {1: 1, 2: 4}, 1: {2: 2, 3: 5}, 2: {3: 1}, 3: {2: 1, 4: 3}, 4: {0: 3, 3: 1}} d, p = dijkstra(graph, 0) print(d) #{0: 0, 1: 1, 2: 3, 3: 4, 4: 3} print(p) #{0: '', 1: 0, 2: 1, 3: 2, 4: 3} ``` 在上述代码中,我们先定义了一个名为init的初始化函数,它接收一个表示图的数据结构和起点的参数,将所有顶点的距离和前一个节点初始化为-1,将起点的距离设置为0。接下来,我们定义了一个名为dijkstra的算法函数,它接收一个表示图的数据结构和起点的参数,返回一个字典d表示起点到各个顶点的距离,另一个字典p表示与每个节点相邻的前一个节点。该算法首先调用初始化函数,将所有节点的距离和前一个节点初始化,然后遍历所有未处理的节点,在其中找到距离起点最短的节点,将其标记为已处理。然后遍历当前节点的所有出边,更新相邻节点的距离和前一个节点。这个过程重复进行,直到所有节点都被处理完。最后,算法返回d和p两个字典表示起点到各个节点的最短距离和前一个节点。 总结来说,Dijkstra算法是一种非常实用的最短路径算法,在实际应用中具有广泛的应用。Python语言中有许多实现该算法的库,也可以通过简单的代码实现。掌握Dijkstra算法实现方法,对于提高编程的实战能力和解决实际问题有很大帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值