C++实现Dijkstra算法

yizhihongxing

C++实现Dijkstra算法攻略

算法简介

Dijkstra算法是一个在加权图中查找单源最短路径的贪心算法。在开始时,所有节点被分为两个集合:已知最短路径的节点和未知最短路径的节点。对于未知最短路径的节点,算法通过已知最短路径的节点来更新这些节点到源点的距离,最终得到源点到图中所有节点的最短路径。

算法步骤

  1. 初始化图中所有节点的距离为无穷大,除源点的距离为0;
  2. 将所有节点加入未知节点集合;
  3. 从未知节点集合中选择一个最近的节点(即到源点距离最小);
  4. 更新该节点的所有邻居节点的距离,如果距离更短,则修改距离;
  5. 重复步骤3-4,直到所有节点均被加入已知节点集合。

C++实现示例:

以下是一个简单的使用邻接矩阵实现Dijkstra算法的示例,其中图的大小为5 * 5。我们以节点2作为源节点。

#include<bits/stdc++.h>
using namespace std;

const int N = 105;
const int INF = 999999;
int n, m;
int graph[N][N];  //邻接矩阵
int d[N];         //存储节点到源点的最短距离
bool vis[N];      //记录节点是否在已知节点集合中

//Dijkstra算法函数
void Dijkstra(int src) {
    memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= n; i++) d[i] = graph[src][i];
    vis[src] = true;
    for (int i = 1; i < n; i++) {  //遍历除源点外的所有节点
        int u = -1, mn = INF;
        for (int j = 1; j <= n; j++) {
            if (!vis[j] && d[j] < mn) {
                u = j;
                mn = d[j];
            }
        }
        if (u == -1) return;  //无法到达目标点
        vis[u] = true;
        for (int j = 1; j <= n; j++) {
            if (!vis[j] && graph[u][j] != INF) {
                d[j] = min(d[j], d[u] + graph[u][j]);
            }
        }
    }
}

int main() {
    cin >> n >> m;
    memset(graph, INF, sizeof(graph));
    for (int i = 1; i <= n; i++) graph[i][i] = 0;
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        graph[u][v] = min(graph[u][v], w);  
        graph[v][u] = min(graph[v][u], w);  //无向图需要加上反向边
    }
    int src = 2;  //源点为2
    Dijkstra(src);
    for (int i = 1; i <= n; i++) {
        cout << d[i] << " ";
    }
    cout << endl;
    return 0;
}

第二个示例是使用邻接表实现Dijkstra算法,相比邻接矩阵每次更新节点的距离时速度更快。相同的,我们以节点2作为源节点。

#include<bits/stdc++.h>
using namespace std;

const int N = 105;
const int INF = 999999;
int n, m;
struct Edge{   //邻接表中的边
    int to, w;
    Edge(int u, int v):to(u),w(v){}
    bool operator < (const Edge &e) const {
        return w > e.w;
    }
};
vector<Edge> graph[N];  //邻接表
int d[N];               //存储节点到源点的最短距离
bool vis[N];            //记录节点是否在已知节点集合中

//Dijkstra算法函数
void Dijkstra(int src) {
    memset(vis, 0, sizeof(vis));
    memset(d, INF, sizeof(d));
    priority_queue<Edge> q;  //使用优先队列,堆优化
    q.push(Edge(src, 0));
    d[src] = 0;
    while(!q.empty()) {
        Edge u = q.top();
        q.pop();
        if(vis[u.to]) continue;
        vis[u.to] = true;
        for(int i = 0; i < graph[u.to].size(); i++) {
            Edge v = graph[u.to][i];
            if(vis[v.to]) continue;
            if(d[v.to] > d[u.to] + v.w) {  //松弛操作,更新距离
                d[v.to] = d[u.to] + v.w;
                q.push(Edge(v.to, d[v.to]));
            }
        }
    }
}

int main() {
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
        int u, v, w;
        cin >> u >> v >> w;
        graph[u].push_back(Edge(v, w));
        graph[v].push_back(Edge(u, w));  //无向图需要加上反向边
    }
    int src = 2;  //源点为2
    Dijkstra(src);
    for(int i = 1; i <= n; i++) {
        cout << d[i] << " ";
    }
    cout << endl;
    return 0;
}

以上两个示例均可在O(n^2)的时间内求解单源最短路径。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++实现Dijkstra算法 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • 比特币原理是什么?比特币原理详解

    比特币原理是什么? 比特币(Bitcoin)是一种去中心化的数字货币,是基于点对点网络技术和密码学算法实现的。它的核心原领是区块链技术,是一种分布式账本技术,使得比特币能够实现去中心化、防篡改。 比特币采用共识机制来保证交易的安全和可靠性。它没有中心化的发行机构,每一笔交易都被记录到区块链上。同时,比特币的发行数量是有限的,最大发行量不超过2100万枚。 比…

    C 2023年5月22日
    00
  • C语言中如何进行字符串操作?

    C语言是一门强大的编程语言,它提供了多种字符串操作函数,让我们能够更方便地进行字符串处理。下面是一个详细的C语言字符串操作攻略。 字符串表示 C语言中,字符串是字符数组,以空字符(\0)结尾。例如: char str[] = "Hello, World!"; 在这个例子中,我们定义了一个字符数组 str,存储了字符串 “Hello, Wo…

    C 2023年4月27日
    00
  • UltraEdit技巧总结

    UltraEdit 技巧总结攻略 简介 UltraEdit 是一款功能强大的文本编辑器,被广泛应用于程序员、系统管理员、DBA 等专业人群的日常工作中。UltraEdit 不仅仅是一个文本编辑器,还拥有丰富的编码、调试、FTP/SFTP 等功能。本文旨在总结 UltraEdit 的常见技巧,帮助使用者提高使用效率和体验。 使用技巧 以下是使用 UltraEd…

    C 2023年5月22日
    00
  • json对象转字符串如何实现

    首先,需要明确一下,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,广泛应用于Web应用程序之间的数据交换。JSON对象是一种由“键/值”对组成的数据结构,可以通过一些库函数将其转化为字符串形式。 下面是JSON对象转字符串的方法: 1.使用JSON.stringify()方法 JSON.stringify()是将…

    C 2023年5月23日
    00
  • 开机0xc000000f进不了系统怎么办?0xc000000f进不了系统修复方法

    开机0xc000000f进不了系统怎么办 问题描述 在开机时,如果系统提示0xc000000f错误,那么说明Windows启动管理器中的某个文件已损坏或被删除,Windows无法正常启动。 修复方法 方法一:使用Windows安装光盘修复启动 将Windows安装光盘插入电脑并重启电脑。 进入Windows安装环境界面,选择语言、时间以及货币格式等信息。 单…

    C 2023年5月23日
    00
  • python 接口返回的json字符串实例

    完整攻略: 在使用Python编写Web接口的时候,常常需要返回数据,而json是最常用的一种数据格式。可以使用Python自带的json包来处理json数据。Python可以将json字符串转换成对象,也可以将对象转换成json格式字符串。 下面简单讲解一下Python中如何处理json数据。 将Python的字典转换成json字符串 使用Python自带…

    C 2023年5月23日
    00
  • C语言中switch语句基本用法实例

    下面我将详细讲解C语言中switch语句的基本用法实例,内容将包括以下几部分: 什么是switch语句? switch语句的语法格式 switch语句实例解析 switch语句的优缺点 switch语句实例展示 1. 什么是switch语句? switch语句是C语言中的一种流程控制语句,它可以根据不同的情况执行不同的代码块。通常情况下,switch语句用于…

    C 2023年5月23日
    00
  • @Async异步线程池以及线程的命名方式

    下面我将为您详细讲解“@Async异步线程池以及线程的命名方式”的攻略。 什么是@Async异步线程池 在Spring中,使用@Async注解来使用异步线程。@Async用于在方法执行时,将方法内的操作放在异步线程中执行,以达到并发执行的效果。在异步方法中,可以使用Future类型来获取异步方法返回的结果。 Spring的@Async注解默认使用的是Simp…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部