C++简单实现Dijkstra算法

C++简单实现Dijkstra算法

什么是Dijkstra算法

Dijkstra算法是一种贪心算法,用于解决带权图的单源最短路径问题。它的主要思想是从起点开始,找到距离它最近的节点,将该节点加入已访问的节点中,然后更新其他节点到起点的距离。重复以上步骤,直到找到终点或者所有的节点都被访问。

算法流程

步骤如下:

  1. 初始化:将起点的距离设为0,其他节点的距离设为无穷大。将所有节点加入集合S中。
  2. 找到S中距离起点最近的节点u,将其加入已访问的节点集合V中。
  3. 对于所有与节点u相邻的节点v,更新其到起点的距离,如果有更短的路径,更新其距离。
  4. 重复步骤2和步骤3,直到所有的节点都被访问过。

示例代码

#include <iostream>
#include <climits>
using namespace std;

const int MAXN = 100005;//可以根据题目要求修改
int d[MAXN];
bool used[MAXN];
int V, E;//V表示节点个数,E表示边的个数

struct edge {
    int to;
    int cost;
};

edge G[MAXN][MAXN];//邻接矩阵存图

void dijkstra(int s) {
    // 初始化
    for (int i = 1; i <= V; i++) {
        d[i] = INT_MAX;//将除了起点之外的节点距离都设置为无穷大
        used[i] = false;
    }
    d[s] = 0;

    while (true) {
        int v = -1;
        for (int u = 1; u <= V; u++) {
            if (!used[u] && (v == -1 || d[u] < d[v])) {
                v = u;
            }
        }
        if (v == -1) {
            break;
        }
        used[v] = true;

        // 更新所有与节点v相邻的节点的距离
        for (int u = 1; u <= V; u++) {
            if (G[v][u].cost != INT_MAX) {//如果u和v之间有边相连
                d[u] = min(d[u], d[v] + G[v][u].cost);//判断是否需要更新距离
            }
        }
    }
}

示例说明

例子1

给定起点S,终点T,求S到T的最短路径。

图中的数字表示边的权值。

      (4)
   S ------ T
  / \      / \
(2) (3) (2) (5)
 /     \  /   \
A        B      C

使用邻接矩阵存图的方式,在程序中输入该图的边的信息,然后使用Dijkstra算法求S到T的最短路径。

int main() {
    V = 4;
    E = 5;

    // 初始化邻接矩阵
    for (int i = 1; i <= V; i++) {
        for (int j = 1; j <= V; j++) {
            G[i][j].cost = INT_MAX;
        }
    }
    G[1][2].cost = 2;
    G[1][3].cost = 3;
    G[2][3].cost = 2;
    G[2][4].cost = 5;
    G[3][4].cost = 4;
    G[2][1].cost = 2;
    G[3][1].cost = 3;
    G[3][2].cost = 2;
    G[4][2].cost = 5;
    G[4][3].cost = 4;

    // 求最短路径
    dijkstra(1);

    // 输出结果:输出所有节点到起点的最短路径
    for (int i = 1; i <= V; i++) {
        cout << "distance from S to " << i << ": " << d[i] << endl;
    }

    return 0;
}

输出结果:

distance from S to 1: 0
distance from S to 2: 2
distance from S to 3: 3
distance from S to 4: 7

例子2

实际应用经常涉及到多个起点或终点的情况,求出这些点到其他节点的最短路径。

例如,从下面的图中的点1、2和7,分别到其他节点的最短路径。

                      (2)
                    /      \
               (4)/           \ (3)
                /               \
               1-------(6)--------2
                \               /
               (5)\           /(4)
                    \      /
                      (1)
                        7

多源最短路径问题可以把每个起点作为开始运行Dijkstra算法,最终获得每个点到起点的最短路径。这种方法叫做 Floyd 算法,时间复杂度较高,但对于较小的图来说是可行的。

// 计算多源最短路径
void floyd() {
    for (int k = 1; k <= V; k++) {
        for (int i = 1; i <= V; i++) {
            for (int j = 1; j <= V; j++) {
                G[i][j].cost = min(G[i][j].cost, G[i][k].cost + G[k][j].cost);
            }
        }
    }
}

int main() {
    V = 7;
    E = 10;

    // 初始化邻接矩阵
    for (int i = 1; i <= V; i++) {
        for (int j = 1; j <= V; j++) {
            if (i == j) {
                G[i][j].cost = 0;
            } else {
                G[i][j].cost = INT_MAX;
            }
        }
    }
    G[1][2].cost = 6;
    G[1][7].cost = 1;
    G[2][1].cost = 6;
    G[2][3].cost = 5;
    G[2][7].cost = 2;
    G[3][2].cost = 5;
    G[3][4].cost = 5;
    G[4][3].cost = 5;
    G[4][5].cost = 4;
    G[5][4].cost = 4;
    G[5][6].cost = 3;
    G[6][5].cost = 3;
    G[6][7].cost = 9;
    G[7][1].cost = 1;
    G[7][2].cost = 2;
    G[7][6].cost = 9;

    // 求多源最短路径
    floyd();

    // 输出结果:输出从点1、2、7到其他节点的最短路径
    cout << "distance from 1 to:" << endl;
    for (int i = 1; i <= V; i++) {
        cout << i << ": " << G[1][i].cost << endl;
    }
    cout << "distance from 2 to:" << endl;
    for (int i = 1; i <= V; i++) {
        cout << i << ": " << G[2][i].cost << endl;
    }
    cout << "distance from 7 to:" << endl;
    for (int i = 1; i <= V; i++) {
        cout << i << ": " << G[7][i].cost << endl;
    }

    return 0;
}

输出结果:

distance from 1 to:
1: 0
2: 6
3: 11
4: 16
5: 20
6: 23
7: 1
distance from 2 to:
1: 6
2: 0
3: 5
4: 10
5: 14
6: 17
7: 2
distance from 7 to:
1: 1
2: 2
3: 7
4: 12
5: 16
6: 9
7: 0

总结

Dijkstra算法可以求单源最短路径问题,时间复杂度为O(N^2),当边很多时会很慢。若边很多(如>10^6,即100W),则可以使用堆优化版的Dijkstra算法,时间复杂度降为O(ElogV)。

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

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

相关文章

  • C语言 结构体(Struct)详解及示例代码

    C语言 结构体(Struct)详解及示例代码 什么是结构体(struct)? 结构体是C语言中一种构造类型(Compound Type),它可以将多个不同类型的变量组合成一个整体,方便在程序中进行操作。 一个结构体可以包含任意数量的成员变量,每个成员变量可以是基本类型,也可以是其他结构体类型。结构体定义语法如下: struct 结构体名称 { 数据类型 成员…

    C 2023年5月24日
    00
  • json转String与String转json及判断对象类型示例代码

    这里是关于”json转String与String转json及判断对象类型示例代码”的详细攻略。 json转String JSON是一种数据格式,在JavaScript中,JSON.stringify()方法可以将一个对象转换为JSON字符串。 const obj = {"name": "Tom", "age&…

    C 2023年5月23日
    00
  • Win7系统打开软件提示错误代码0xc0000022是什么原因?怎么解决?

    Win7系统打开软件提示错误代码0xc0000022的原因 当Windows 7系统出现错误代码0xc0000022时,表示发生了访问认证错误,无法打开指定的软件。这个错误有多种原因,其中两个最常见的原因是权限问题和受损的软件。 权限问题 如果您不具有打开某个软件的访问权限,则会触发此错误。当您在不具有管理员权限的用户账户下尝试打开受保护的应用程序或系统应用…

    C 2023年5月23日
    00
  • c++ #include是怎么样工作的?

    当我们在编写 C++ 程序时, 有时需要使用其它文件中定义的函数或变量,那么我们就需要使用 #include 语句把这个文件包含进来。在 C++ 中,#include 是一个预处理命令。 下面来详细讲解“C++ #include 是怎么样工作的?”的完整攻略: 1. #include 的作用 include 是 C++ 中的一个预处理命令,用于包含一个文件到…

    C 2023年5月23日
    00
  • C++嵌入式内存管理详情

    关于C++嵌入式内存管理,以下是完整的攻略: C++嵌入式内存管理概述 在嵌入式系统开发中,动态内存的使用是非常受限的,因此需要采用静态内存管理或者是内存池来代替动态内存分配。C++ 的运行时库也支持内存池技术,可以用于嵌入式系统开发中。 C++ 的内存池管理主要依赖于 new 和 delete 运算符来实现,通过重载 new 和 delete 运算符来达到…

    C 2023年5月23日
    00
  • C语言实现简单的停车场管理系统

    C语言实现简单的停车场管理系统 概述 本文介绍如何使用C语言实现简单的停车场管理系统。该系统支持车辆的进入、离开以及查询停车场内的车辆信息等基本功能。 实现步骤 1. 设计数据结构 首先需要设计一个数据结构来表示车辆的信息,包括车牌号、入场时间等。我们可以定义一个结构体来表示车辆信息,如下所示: typedef struct Car { char licen…

    C 2023年5月22日
    00
  • 详解C++ 模板编程

    详解C++ 模板编程攻略 什么是模板编程 模板编程是一种C++编程技术,利用它可以编写具有通用性和可重用性的代码。使用模板编程技术,我们可以让我们的代码更加灵活且容易扩展。 模板编程主要依托于C++的模板(template)机制,通过在编译期间对类型参数进行自动推导,以实现代码的通用性和类型无关性。 模板的解析 在C++中,我们可以通过template来声明…

    C 2023年5月23日
    00
  • C++如何实现定长内存池详解

    C++实现定长内存池的详细攻略如下: 什么是定长内存池 定长内存池是一种用于管理内存分配和释放的方法。相对于动态内存分配和释放,定长内存池可以更高效地管理内存,因为它不需要频繁地进行内存分配和释放操作,而是预先分配一块连续的内存空间,然后在此基础上进行内存管理。 定长内存池的实现方法 在C++中,我们可以使用标准库中的std::vector或者自己实现一个内…

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