C++简单实现Dijkstra算法

yizhihongxing

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++键盘记录程序代码

    C++键盘记录程序代码攻略 简介 键盘记录程序可以记录用户在键盘上输入的所有内容,包括敲击的键和输入的文字。在开发键盘记录程序时,我们需要了解底层的键盘输入原理和如何获取键盘输入事件。在本文中,我们将演示如何使用C++语言编写一个简单的键盘记录程序。 实现步骤 步骤1:打开键盘输入设备 在Windows操作系统中,键盘输入设备通常被称为“HID(Human …

    C 2023年5月23日
    00
  • C语言实现学籍管理系统

    C语言实现学籍管理系统攻略 一、需求分析 学籍管理系统需要具备以下功能:1. 添加学生信息2. 修改学生信息3. 删除学生信息4. 查询学生信息5. 查看全部学生信息 二、设计思路 学籍管理系统的数据结构可以使用链表来实现,具体分为两个结构体:教务处(包含链表头)和学生。其中教务处是包含多个学生的一个链表,学生则是链表中的一个节点。 具体实现思路如下:1. …

    C 2023年5月23日
    00
  • C++实现简单版图书管理系统

    C++实现简单版图书管理系统攻略 本文将介绍如何使用C++语言实现简单版图书管理系统。本系统主要包含以下功能:添加图书信息、删除图书信息、查看图书信息、修改图书信息、退出系统。 设计思路 在开始实现之前,我们需要先确定程序的设计思路。将所有的操作封装成一个类,来实现图书的添加、删除、修改、查询等操作。同时,我们需要设计出一个图书类,包含图书的基本信息。 代码…

    C 2023年5月23日
    00
  • MySQL系列之开篇 MySQL关系型数据库基础概念

    MySQL系列之开篇 MySQL关系型数据库基础概念 什么是关系型数据库? 关系型数据库是最为常见的数据库类型,它使用了表格来存储数据,每个表格都有一个唯一的名字,并且由一个或多个列组成。 在关系型数据库中,表格之间可以相互关联,从而形成一个关系型的数据模型。 关系型数据库的优点 简单易学,广泛使用。 数据之间的关系清晰。 可靠性、稳定性好。 支持事务处理,…

    C 2023年5月22日
    00
  • Windows10无法快速启动错误代码0xC000007B如何修复

    Windows10无法快速启动错误代码0xC000007B如何修复 在使用Windows10时,有时候会遇到无法快速启动的问题,其中错误代码0xC000007B是其中一种较为常见的错误。 问题描述 当你启动Windows10电脑时,屏幕可能会出现“Your PC/Device needs to be repaired”的字样,伴随着错误代码0xC000007…

    C 2023年5月23日
    00
  • 三星SLC410W打印机怎么清除纸盘中卡纸?

    清除三星SLC410W打印机纸盘卡纸,可以按照以下步骤进行操作: Step 1:确认纸盘是否卡纸 首先,需要确认打印机是否确实存在纸张卡纸的情况,可以通过以下方式进行判断: 打开打印机的纸盘抽屉,检查是否有纸张卡在了进纸口或者出纸口。 检查打印机的显示屏是否显示有卡纸的提示信息。 检查打印机是否出现异常的声音或者闪烁的LED灯。 如果以上任何一种情况出现,就…

    C 2023年5月23日
    00
  • C语言实现520表白代码 祝你表白成功!

    C语言实现520表白代码攻略 感谢您对C语言表白代码的关注。下面是实现520表白代码的完整攻略。 1. 准备工作 在开始实现520表白代码之前,需要安装C语言编译器。在Windows系统上,我们建议使用MinGW或者Visual Studio Code(带有C/C++扩展)作为编译器;在Linux系统上,可以使用GCC。 2. 编写C程序 我们可以通过在C程…

    C 2023年5月23日
    00
  • Win10怎么设置MTU值加快WIFI速度?

    针对“Win10怎么设置MTU值加快WIFI速度?”这个问题,下面是我提供的完整攻略: 1. 了解MTU值 MTU(Maximum Transmission Unit)即最大传输单元,是每个数据包可以传输的最大数据量。通常情况下,MTU值越大,一个数据包就可以携带更多的数据,从而提高网络传输效率。但如果MTU值设置得过大,会增加传输过程中出现网络问题的风险。…

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