Dijkstra算法

1.前言
迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。主要用于求解从一个源节点到其他所有节点的最短路径问题,解决的是有权图中最短路径问题。Dijkstra算法应用十分广泛。在网络路由上,路由协议(如OSPF和IS-IS)中,Dijkstra算法用于计算网络中的最短路径,从而确定数据包的转发路径。在无线传感器网络或移动自组织网络中,Dijkstra算法可以帮助寻找最低能耗路径或最可靠的通信路径。在地理信息系统(GIS)方面,导航系统:如Google Maps、百度地图、高德地图和GPS设备,使用Dijkstra算法来计算最短路径,以提供最佳驾驶或步行路线。在路径规划方面,机器人导航中,Dijkstra算法用于计算机器人在环境中的最短路径,避免障碍物并到达目标位置等等。

2.算法思想
如图2.1所示,是一张图,边上的值表示表示权重,在不同的应用中权重可表示不同的意思。下面我以这一张图来简介算法步骤。设G=(V,E)是一个带权有向图,把图中节点集合V分成两组,第一组为已求出最短路径的节点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径, 就将该节点加入到集合S中,直到全部节点都加入到S中,算法就结束了);第二组为其余未确定最短路径的节点集合(用U表示),按最短路径长度的递增次序依次把第二组的节点加入S中。在加入的过程中,总保持从源点v到S中各节点的最短路径长度不大于从源点v到U中任何节点的最短路径长度。 此外,每个节点对应一个距离,S中的节点的距离就是从v到此节点的最短路径长度,U中的节点的距离,是从v到此节点只包括S中的节点为中间节点的当前最短路径长度。

图2.1 一张图表

在这里插入图片描述
从D节点开始,把D节点加入S集合,其余的还是在U集合中,D节点的邻居有C,E节点,计算距离,其他节点没有相邻故是无穷大。3小于4,故将C加入S集合中。此时B,F也相邻,计算出距离。由于D-C-E的距离8是大于D-E距离4的,故D-E的距离不更新。下一次离集合S最近的点是E,把E加入S集合,由于D-E-F距离6小于DCF距离9,故更新D到F的值。如图所以,一直到集合U中的元素为0。节点D到各个节点的最短距离就被找了出来。
在这里插入图片描述

图2.2 选取节点过程

3.代码
pyhon代码

import heapq  
  
def dijkstra(graph, start):  
    # 初始化距离字典,将起始节点的距离设为0,其他节点设为无穷大  
    distances = {node: float('infinity') for node in graph}  
    distances[start] = 0  
  
    # 初始化一个最小堆来存储节点和距离,以便能够按距离提取最小节点  
    priority_queue = [(0, start)]  
  
    # 当优先队列不为空时,继续执行  
    while priority_queue:  
        # 提取距离最小的节点  
        current_distance, current_node = heapq.heappop(priority_queue)  
  
        # 如果当前节点的距离已经大于优先队列中记录的距离,则跳过  
        if current_distance > distances[current_node]:  
            continue  
  
        # 遍历当前节点的所有邻居  
        for neighbor, weight in graph[current_node].items():  
            # 计算通过当前节点到达邻居节点的距离  
            distance = current_distance + weight  
  
            # 如果找到一条更短的路径,则更新距离并添加/更新邻居节点到优先队列  
            if distance < distances[neighbor]:  
                distances[neighbor] = distance  
                heapq.heappush(priority_queue, (distance, neighbor))  
  
    return distances  
  
# 示例图(使用邻接列表表示)  
graph = {  
    'A': {'B': 1, 'C': 4},  
    'B': {'A': 1, 'C': 2, 'D': 5},  
    'C': {'A': 4, 'B': 2, 'D': 1},  
    'D': {'B': 5, 'C': 1}  
}  
  
# 使用 Dijkstra's 算法从节点 'A' 开始计算最短路径  
print(dijkstra(graph, 'A'))  # 输出: {'A': 0, 'B': 1, 'C': 3, 'D': 4}

c++代码

#include <iostream>  
#include <vector>  
#include <queue>  
#include <climits>  
#include <unordered_map>  
  
using namespace std;  
  
// 使用pair作为优先队列的元素,其中first是距离,second是节点  
typedef pair<int, int> PII;  
  
// Dijkstra算法  
vector<int> dijkstra(const vector<vector<pair<int, int>>>& graph, int start) {  
    int num_nodes = graph.size();  
    vector<int> distances(num_nodes, INT_MAX); // 初始化所有节点的距离为无穷大  
    distances[start] = 0; // 源节点的距离为0  
  
    // 优先队列用于存储待处理的节点,按照距离从小到大排序  
    priority_queue<PII, vector<PII>, greater<PII>> pq;  
    pq.push({0, start}); // 将源节点入队  
  
    while (!pq.empty()) {  
        int curr_dist = pq.top().first; // 当前距离  
        int curr_node = pq.top().second; // 当前节点  
        pq.pop();  
  
        // 如果当前节点的距离已经被更新过,则跳过  
        if (curr_dist > distances[curr_node]) continue;  
  
        // 遍历当前节点的所有邻居  
        for (const auto& neighbor : graph[curr_node]) {  
            int next_node = neighbor.first;  
            int weight = neighbor.second;  
  
            // 计算通过当前节点到达下一个节点的距离  
            int new_dist = curr_dist + weight;  
  
            // 如果找到了一条更短的路径,则更新距离  
            if (new_dist < distances[next_node]) {  
                distances[next_node] = new_dist;  
                pq.push({new_dist, next_node}); // 将下一个节点入队  
            }  
        }  
    }  
  
    return distances;  
}  
  
int main() {  
    // 示例图(使用邻接列表表示)  
    vector<vector<pair<int, int>>> graph = {  
        {{1, 4}, {0, 1}}, // A连接到B和C,距离分别为1和4  
        {{0, 1}, {1, 2}, {2, 5}}, // B连接到A、C和D,距离分别为1、2和5  
        {{0, 4}, {1, 2}, {3, 1}}, // C连接到A、B和D,距离分别为4、2和1  
        {{2, 5}, {3, 1}} // D连接到B和C,距离分别为5和1  
    };  
  
    // 假设节点从0开始编号(A为0,B为1,依此类推)  
    int start_node = 0; // 从A节点开始  
  
    // 使用Dijkstra算法计算最短路径  
    vector<int> distances = dijkstra(graph, start_node);  
  
    // 输出结果  
    for (int i = 0; i < distances.size(); ++i) {  
        cout << "Distance from node " << start_node << " to node " << i << ": " << distances[i] << endl;  
    }  
  
    return 0;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值