C++实现Dijkstra算法

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日

相关文章

  • C++实现地铁自动售票系统程序设计

    C++实现地铁自动售票系统程序设计攻略 概述 地铁自动售票系统是一种基于计算机技术的智能化自助售票系统,可以方便快捷地为乘客提供地铁车票的购买、充值、查询、退款等服务。本文主要介绍如何使用C++语言实现地铁自动售票系统的设计以及开发方法。 实现步骤 第一步:确定功能需求 地铁自动售票系统的主要功能包括: 售卖地铁票和充值。要求用户输入选择的地铁线路和数量,然…

    C 2023年5月23日
    00
  • 浅谈C语言数组元素下标为何从0开始

    关于C语言数组元素下标为何从0开始的问题,经过长期的发展和实践,现在已经成为C语言的基本规则之一。在这里,我将详细讲解为什么C语言数组下标从0开始,以及这种方式的优势和成本。 为什么C语言数组元素下标从0开始? 在C语言中,数组是一组数据的集合,它们具有相同的类型。数组中的每个元素都有一个唯一的索引,通过该索引可以访问该数组的元素。C语言数组元素下标从0开始…

    C 2023年5月23日
    00
  • C程序 查找两个数组之间的共同数组元素

    下面我将详细介绍如何使用C程序查找两个数组之间的共同数组元素。 题目背景 假设我们有两个整数数组 array1 和 array2,现在需要找出这两个数组之间共同的元素,并输出这些元素。例如: array1 = {1, 3, 5, 7, 9}; array2 = {2, 3, 4, 7, 8}; 则两个数组之间共同的元素是 3 和 7。 解题思路 我们可以使用…

    C 2023年5月9日
    00
  • json简单介绍

    下面我来为你详细讲解关于“JSON简单介绍”的完整攻略。 什么是JSON? JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它采用类似于 JavaScript 对象字面量的语法,易于人阅读和编写,同时也易于机器解析和生成。JSON是一种文本格式,可以被任何编程语言解析和生成,不依赖于任何语言环境。 JSON的语法规…

    C 2023年5月23日
    00
  • 在C++中反射调用.NET的方法(二)

    在C++中反射调用.NET的方法的攻略可以分为以下几个步骤: 1. 首先需要准备好以下环境 Visual Studio 开发环境(如版本为VS 2019) C++/CLI Windows窗体应用程序,或其他CLI类型项目 .NET Framework SDK(如版本为.NET Framework 4.7.2) 被调用的.NET程序集(如例子中的DLL文件) …

    C 2023年5月22日
    00
  • C语言连续生成随机数的实现方法

    C语言中生成随机数的方法是通过调用函数库中的rand()函数来实现的。但是由于rand()函数是伪随机数生成器,每次生成的随机数序列是相同的,除非使用srand()函数来改变种子值。而有些时候需要生成一组不同的随机数序列,或者需要在程序的不同地方生成不同的随机数序列,这时就需要使用不同的种子值。因此,需要实现连续生成随机数的功能。 下面是实现连续生成随机数的…

    C 2023年5月22日
    00
  • C++课程设计之图书馆管理系统

    C++课程设计之图书馆管理系统攻略 1. 项目概述 图书馆管理系统是管理图书馆日常工作的应用软件,主要功能包括图书的借阅、归还、查询等。本项目使用C++语言实现图书馆管理系统。 2. 功能需求 本项目需要实现以下功能: 学生信息的录入和管理 图书信息的录入和管理 图书的借阅和归还 图书的查询和统计 3. 实现步骤 3.1 设计数据结构 首先需要设计对应的数据…

    C 2023年5月23日
    00
  • 关于bat脚本中的命令状态码相关的%errorlevel%变量问题

    关于bat脚本中的命令状态码相关的%errorlevel%变量问题 在bat脚本中,我们通常会执行一些命令,如ping、dir等等。这些命令执行完毕后,会返回一个状态码,用来表示命令是否成功执行以及发生了什么错误。在bat脚本中,我们可以通过%errorlevel%变量来获取这个状态码。本文将详细讲解%errorlevel%变量的使用方式和相关注意事项。 获…

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