算法 - 图论Dijkstra(原理、思路代码实现、以东南大学真题为例讲解手算方法)

news2024/9/20 8:42:49

Dijkstra

算法原理
Dijkstra算法是一种经典的用于计算单源最短路径的算法。它可以在带权重的图中找到从源节点到所有其他节点的最短路径。Dijkstra算法通过贪心策略,不断选择当前已知最短路径最小的节点,更新其邻接节点的路径长度,直到处理完所有节点。

适用场景

  • 图中的边权重为非负值。
  • 需要计算从单一源点到其他所有节点的最短路径。

算法步骤

  1. 初始化:设定源节点的距离为0,其他所有节点的距离为无穷大。将所有节点标记为未访问状态。
  2. 从未访问节点中选择距离最小的节点作为当前节点。
  3. 对于当前节点的每一个未访问的邻接节点,计算从源节点经过当前节点到达该邻接节点的距离。如果该距离小于之前记录的距离,则更新该距离。
  4. 标记当前节点为已访问状态。
  5. 重复步骤2-4,直到所有节点都被访问过。

实现步骤

  1. 使用一个数组或字典记录每个节点的当前最短路径。
  2. 使用一个优先队列(最小堆)加速获取当前最短路径最小的节点。
  3. 不断从优先队列中取出最短路径最小的节点,更新其邻接节点的路径长度。
  4. 直到优先队列为空,所有节点的最短路径均已确定。

伪代码

function Dijkstra(Graph, source):
    dist[source] = 0
    create priority queue Q
    for each vertex v in Graph:
        if v ≠ source:
            dist[v] = infinity
            prev[v] = undefined
        Q.add_with_priority(v, dist[v])

    while Q is not empty:
        u = Q.extract_min()
        for each neighbor v of u:
            alt = dist[u] + length(u, v)
            if alt < dist[v]:
                dist[v] = alt
                prev[v] = u
                Q.decrease_priority(v, alt)

    return dist, prev

C语言代码

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define V 9  // 图中的顶点数

// 寻找当前未访问节点中距离最小的节点
int minDistance(int dist[], int sptSet[]) {
    int min = INT_MAX, min_index;
    for (int v = 0; v < V; v++) {
        if (sptSet[v] == 0 && dist[v] <= min) {
            min = dist[v], min_index = v;
        }
    }
    return min_index;
}

// 打印从源节点到所有其他节点的最短路径
void printSolution(int dist[]) {
    printf("Vertex \t Distance from Source\n");
    for (int i = 0; i < V; i++) {
        printf("%d \t\t %d\n", i, dist[i]);
    }
}

// 实现Dijkstra算法
void dijkstra(int graph[V][V], int src) {
    int dist[V];  // 存储源节点到其他节点的最短距离
    int sptSet[V];  // 标记节点是否已被处理

    // 初始化所有节点的最短距离为无穷大,sptSet为未访问状态
    for (int i = 0; i < V; i++) {
        dist[i] = INT_MAX, sptSet[i] = 0;
    }
    dist[src] = 0;

    // 遍历所有节点
    for (int count = 0; count < V - 1; count++) {
        int u = minDistance(dist, sptSet);
        sptSet[u] = 1;

        // 更新节点的最短路径
        for (int v = 0; v < V; v++) {
            if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v]) {
                dist[v] = dist[u] + graph[u][v];
            }
        }
    }
    printSolution(dist);
}

int main() {
    int graph[V][V] = {{0, 4, 0, 0, 0, 0, 0, 8, 0},
                       {4, 0, 8, 0, 0, 0, 0, 11, 0},
                       {0, 8, 0, 7, 0, 4, 0, 0, 2},
                       {0, 0, 7, 0, 9, 14, 0, 0, 0},
                       {0, 0, 0, 9, 0, 10, 0, 0, 0},
                       {0, 0, 4, 14, 10, 0, 2, 0, 0},
                       {0, 0, 0, 0, 0, 2, 0, 1, 6},
                       {8, 11, 0, 0, 0, 0, 1, 0, 7},
                       {0, 0, 2, 0, 0, 0, 6, 7, 0}};
    dijkstra(graph, 0);
    return 0;
}

代码解释

  • int minDistance(int dist[], int sptSet[]):找到未访问节点中距离最小的节点。
  • void printSolution(int dist[]):打印从源节点到所有其他节点的最短路径。
  • void dijkstra(int graph[V][V], int src):实现Dijkstra算法,从源节点计算到所有其他节点的最短路径。
  • int main():主函数,定义图的邻接矩阵并调用Dijkstra算法计算最短路径。

算法特点

  • 时间复杂度:O(V^2)(使用数组实现优先队列时),使用二叉堆可以优化到O((V + E) log V)。
  • 适用于图中的边权重为非负值的情况。
  • 通过贪心策略逐步找到从源节点到其他节点的最短路径。

通过上述代码和解释,读者应该可以理解Dijkstra算法的原理和实现步骤,并在实际应用中使用该算法计算最短路径。对于考研初试,只需掌握手算方法,我们以东南大学2000年真题为例进行讲解:
在这里插入图片描述

初始状态:

节点距离前驱
a0-
b-
c-
d-
e-
f-
g-

Round 1:

选择距离最小的节点a,更新其邻接节点的距离。

  • 更新节点c的距离为2(0 + 2),前驱为a。
  • 更新节点d的距离为12(0 + 12),前驱为a。
  • 更新节点b的距离为15(0 + 15),前驱为a。
节点距离前驱
a0-
b15a
c2a
d12a
e-
f-
g-

Round 2:

选择距离最小的节点c,更新其邻接节点的距离。

  • 更新节点e的距离为10(2 + 8),前驱为c。
  • 更新节点f的距离为6(2 + 4),前驱为c。
节点距离前驱
a0-
b15a
c2a
d12a
e10c
f6c
g-

Round 3:

选择距离最小的节点f,更新其邻接节点的距离。

  • 更新节点d的距离为11(6 + 5),前驱为f。
  • 更新节点g的距离为16(6 + 10),前驱为f。
节点距离前驱
a0-
b15a
c2a
d11f
e10c
f6c
g16f

Round 4:

选择距离最小的节点e,更新其邻接节点的距离。

  • 节点e没有需要更新的邻接节点。
节点距离前驱
a0-
b15a
c2a
d11f
e10c
f6c
g16f

Round 5:

选择距离最小的节点d,更新其邻接节点的距离。

  • 更新节点g的距离为13(11 + 2),前驱为d。
节点距离前驱
a0-
b15a
c2a
d11f
e10c
f6c
g13d

Round 6:

选择距离最小的节点g,更新其邻接节点的距离。

  • 节点g没有需要更新的邻接节点。
节点距离前驱
a0-
b15a
c2a
d11f
e10c
f6c
g13d

Round 7:

选择距离最小的节点b,更新其邻接节点的距离。

  • 节点b没有需要更新的邻接节点。
节点距离前驱
a0-
b15a
c2a
d11f
e10c
f6c
g13d

最终结果如下:

最短路径结果:

  • a -> a: 0
  • a -> b: 15 (路径:a-b)
  • a -> c: 2 (路径:a-c)
  • a -> d: 11 (路径:a-c-f-d)
  • a -> e: 10 (路径:a-c-e)
  • a -> f: 6 (路径:a-c-f)
  • a -> g: 13 (路径:a-c-f-d-g)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1939471.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux之旅:常用的指令,热键和权限管理

目录 前言 1. Linux指令 &#xff08;1&#xff09; ls &#xff08;2&#xff09; pwd 和 cd &#xff08;3&#xff09;touch 和 mkdir &#xff08;4&#xff09; rmdir 和 rm &#xff08;5&#xff09;cp &#xff08;6&#xff09;mv &#xff08;7&#xff09;…

Qt窗口介绍

Qt窗口 一、Qt窗口二、菜单栏创建菜单栏在菜单栏中添加菜单创建菜单项在菜单项之间添加分割线综合练习 三、工具栏创建工具栏设置停靠位置设置浮动属性设置移动属性综合练习 四、状态栏状态栏的创建在状态栏中显示实时消息在状态栏显示永久的消息 五、浮动窗口浮动窗口的创建设…

达梦数据库系列—29. DTS迁移ORACLE到DM

目录 1.ORACLE源端信息 2.DM目的端信息 3.DTS 迁移评估 4.数据库迁移 4.1 Oracle 源端数据库准备 4.2 目的端达梦数据库准备 初始化参数设置 兼容性参数设置 表空间规划 用户规划 创建迁移用户和表空间 4.3迁移步骤 创建迁移 配置数据源 配置迁移对象及策略 开…

Vue3 --- 路由

路由就是一组key-value的对应关系&#xff1b;多个路由&#xff0c;需要经过路由器的管理。 1. 基本切换效果 安装路由器 npm i vue-router /router/index.ts // import { createRouter, createWebHistory } from vue-router import Home from /components/Home.vue import…

[Armbian] 部署Docker版Home Assistent,安装HACS并连接米家设备

title: [Armbian] 部署Docker版Home Assistent&#xff0c;安装HACS并连接米家设备 date: 2024-07-21T10:51:23Z lastmod: 2024-07-21T11:40:39Z [Armbian] 部署Docker版Home Assistent&#xff0c;安装HACS并连接米家设备 官网&#xff1a;Home Assistant (home-assistant.i…

算法——滑动窗口(day6)

1004.最大连续1的个数 ||| 1004. 最大连续1的个数 III - 力扣&#xff08;LeetCode&#xff09; 题目解析&#xff1a; 这道题如果能转化为滑动窗口的话就会很简单&#xff0c;因为我们如果尝试去把0翻转为1再计数的话等到第2轮又得重新翻转回来&#xff0c;费时费力~ 那么我…

gihub导入gitee仓库实现仓库同步

昨天在GitHub里导入了gitee仓库&#xff0c;但是在仓库同步这里卡了很久&#xff0c;因为网上大多数都是从github导入gitee&#xff0c;然后github生成token放入实现同步&#xff0c;但是我找到一种更为方便的&#xff01; 1.首先找到项目文件下的.git文件里的config文件 2.在…

linux 下将文件安装的mysql.server服务添加到systemctl中管理

1、找到mysql 的 mysql.server/ 文件位置 find / -name mysql.server 2、编辑mysql.server脚本&#xff0c;并将mysql.server脚本添加到linux服务 3、将mysql.server 复制到etc/init.d/mysqld 目录 cp /app/db/mysql/support-files/mysql.server /etc/init.d/mysqld 4、授权…

08 B端产品业务调研的流程(1)

业务调研是掌握业务情况的有效方法。一般核心流程如下图&#xff1a; 明确调研目标&#xff1a;即调研的目标&#xff0c;解决为什么要做业务调研&#xff0c;期望解决什么问题&#xff0c;达到什么样效果&#xff0c;定向。 选取调研对象&#xff1a;涉及多角色&#xff0c;一…

【吊打面试官系列-ZooKeeper面试题】zookeeper 负载均衡和 nginx 负载均衡区别?

大家好&#xff0c;我是锋哥。今天分享关于 【zookeeper 负载均衡和 nginx 负载均衡区别? 】面试题&#xff0c;希望对大家有帮助&#xff1b; zookeeper 负载均衡和 nginx 负载均衡区别? zk 的负载均衡是可以调控&#xff0c;nginx 只是能调权重&#xff0c;其他需要可控的都…

heic文件怎么转换成jpg?上百份文件转换3秒就能搞定(办公必备)

heic和jpg是两种不同的图片格式&#xff0c;平时整理图片素材时&#xff0c;如果需要将heic转为jpg格式&#xff0c;那么可以使用相关的heic图片转换工具。 ​ 为什么要将heic文件转换成jpg&#xff1f;虽然HEIC格式具有很多优点&#xff0c;但是目前并不是所有设备和应用程序…

IAR环境下STM32+IAP方案的实现

--基于STM32F103ZET6的UART通讯实现 一、什么是IAP&#xff0c;为什么要IAP IAP即为In Application Programming(在应用中编程)&#xff0c;一般情况下&#xff0c;以STM32F10x系列芯片为主控制器的设备在出厂时就已经使用J-Link仿真器将应用代码烧录了&#xff0c;如果在设备使…

【Qt】按钮的属性相关API

目录 一. QPushButton 二. QRadioButton 按钮组 三. QCheckBox Qt中按钮的继承体系如下图 QAbstractButton是一个抽象类&#xff0c;集成了按钮的核心属性和API 按钮说明QPushButton&#xff08;普通按钮&#xff09;最常见的按钮&#xff0c;用于触发操作或者事件。可以设…

【Git命令】git rebase之合并提交记录

使用场景 在本地提交了两个commit&#xff0c;但是发现根本没有没必要分为两次&#xff0c;需要想办法把两次提交合并成一个提交&#xff1b;这个时候可以使用如下命令启动交互式变基会话&#xff1a; git rebase -i HEAD~N这里 N 是你想要重新调整的最近的提交数。 如下在本地…

27.js实现鼠标拖拽

e.offsetX是鼠标距离准确事件源的左上角距离 e.clientX是鼠标距离浏览器可视窗口左上角的距离 e.pageX是鼠标距离文档左上角的距离 /* 当鼠标点击div时开始挪动&#xff0c;当鼠标抬起&#xff0c;div静止——事件源是div 当鼠标点击后,鼠标在移动——事件源…

视频汇聚,GB28181,rtsp,rtmp,sip,webrtc,视频点播等多元异构视频融合,视频通话,视频会议交互方案

现在视频汇聚&#xff0c;视频融合和视频互动&#xff0c;是视频技术的应用方向&#xff0c;目前客户一般有很多视频的业务系统&#xff0c;如已有GB28181的监控&#xff08;GB现在是国内主流&#xff0c;大量开源接入和商用方案&#xff09;&#xff0c;rtsp设备&#xff0c;音…

Spring Boot 笔记1(启动类与控制器)

采用Spring Tool Suit 4 java jdk 17 学习启动类与控制器 创建Spring Starter Project 如果https://start.spring.io链接无效&#xff0c;可以选择https://start.aliyun.com 项目结构 启动类 启动类是程序的执行入口 例子1 Demo1Application.java package com.example.dem…

从0开始的STM32HAL库学习6

外部时钟源选择 配置环境 选择TIM2 配置红色框图中的各种配置 时钟源选择外部时钟 2 1. 预分频器 Prescaler &#xff0c;下面填0&#xff0c;不分频 2. 计数模式 CounterModer &#xff0c;计数模式选择为向上计数 3. 自动重装寄存器 CouterPeriod &#xff0c;自动重…

记录些MySQL题集(17)

一、MySQL索引为何使用B树结构&#xff1f; MySQL的索引机制中&#xff0c;默认使用BTree作为底层的数据结构&#xff0c;但为什么要选择B树呢&#xff1f;有人会说树结构是以二分法查找数据&#xff0c;所以会在很大程度上提升检索性能&#xff0c;这点确实没错&#xff0c;但…

企业邮件系统管理(一)掌握企业邮件系统管理:从Exchange Server 2010的安装到高可用性配置

&#x1f44d; 个人网站&#xff1a;【洛秋资源小站】 掌握企业邮件系统管理&#xff1a;从Exchange Server 2010的安装到高可用性配置 在当今的企业环境中&#xff0c;电子邮件系统是不可或缺的通信工具。为了确保企业邮件系统的稳定运行和高效管理&#xff0c;系统管理员需要…