C++迪杰斯特拉算法求最短路径

简介: 一:算法历史   迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。

一:算法历史
  迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
二:算法思想
  按路径长度递增次序产生算法:
  把顶点集合V分成两组:
  (1)S:已求出的顶点的集合(初始时只含有源点V0)
  (2)V-S=T:尚未确定的顶点集合
  将T中顶点按递增的次序加入到S中,保证:
  (1)从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度
  (2)每个顶点对应一个距离值
  S中顶点:从V0到此顶点的长度
  T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度
  依据:可以证明V0到T中顶点Vk的,或是从V0到Vk的直接路径的权值;或是从V0经S中顶点到Vk的路径权值之和
三:应用举例
  (1)题目:编写一个校园导游程序,为来访的客人提供各种信息查询服务。
    主要功能:1.设计学校的校园平面图,所含景点不少于10个:顶点表示景点,边表示路径等;
         2.为客人提供图中任意景点相关信息的查询;
         3.为客人提供图中任意景点的问路查询,即查询人以景点间的一条最短路径。
      要求:1.设计一个主界面;
              2.设计功能菜单,供用户选择
              3.有一定的实用性。
  (2)设计思路:
    1、该题主要有算法思路以及程序的逻辑思路,首先从逻辑思路讲,进入程序,首先设计一个主菜单,选项有景点信息查询,最短路径查询以及显示景点的平面视图三个子菜单,然后根据用户的输入选择的子菜单前的编号,分进入不同的子菜单;该功能是由if….else if…. 语句实现。在景点信息查询和最短路径查询子菜单下还有二级子菜 单,都是列 出所有景点并在前面编号,查询景点信息时,输入景点前面的编号即可,查询最短路径时,先输入起点的编号,再输入终点的编号。而显示景点视图则调用景点平面图函数即可显 示。
    2、算法思路主要是迪杰斯特拉算法的思路,利用迪杰斯特拉算法求最短路径。
    3、先定义好图的储存结构,本题采用邻接矩阵的方式来表示图,并在主函数中初始化该图;
    4、定义三个全局一维数组,一个bool类型数组S[]用来记录从v0到vi是否已经确定了最短路径,是则记S[i]=true,否记S[i]= flase;一个int 类型数组Path[]用来记录从v0到vi的当前最短路径上的vi的直接前驱顶点编号,若v 到vi之间有边则记Path[i] = v的编号,否则记Path[i] = -1;最后一个数组D[]用来记录从v0到vi之间的最短路径长度,存在则记v0到vi之间边的权值或者权值和,否则记为MAX
    5、定义一个求最短路径的函数,传入的参数为图和起点,首先进行初始化工作,初始化S[]数组全为false,D[]数组初始化为起点到各个顶点的权值,Path[]数组初始化为起点是否与各顶点有边,有则记v0否则记-1;
    6、然后进行n-1次for循环,找出vo到其余n-1个顶点之间的最短路径,比较当前D[]数组中最小值,找到最小值的编号v,该编号就是从v0出发到所有顶点中距离最短的顶点编号,然后把S[v]的值置为true。说明从v0出发到顶点v已经找到最短路径;
    7、接着就要更新D[]数组,因为D[]数组是记录最短路径的,现在已经找到了一个顶点的最短路径,已该顶点v为中间点,判断从该顶点v出发到剩下的顶点的路径长度加上该点到v0的路径长度是否小于直接从v0出发到其余顶点的路径长度,如果小于,则更新D[i]为以该顶点v为中间点求得的路径长度。更新Path[i] = v;即i的前驱不再是v0而是v;
    8、循环(6)(7)两步n-1次即可得到D[]数组,输出D[]数组既是v0到所有顶点的最短路径长度;

  (3)源代码:

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
/**
 *作者:Dmego
 *时间:2016-12-12
 */
#define MAX 1000000  //表示极大值∞
#define max 10
bool S[max];   //记录从源点V0到终点Vi是否已经确定为最短路径,确定了记true,否则记false
int Path[max]; //记录从源点V0到终点Vi的当前最短路径上终点Vi的直接前驱顶点序号,若V0到Vi之间有边前驱为V0否则为-1 
int D[max];  //记录源点到终点之间最短路径的长度,存在记V0到Vi的边的权值,否则记为MAX       
typedef struct
{
    string vexs[max];       //顶点表
    int arcs[max][max];      //邻接矩阵        
    int vexnum, arcnum;    //图当前点数和边数

}AMGraph;
//利用迪杰斯特拉算法求最短路径
void ShortestPath_DIJ(AMGraph &G, int v0)
{//使用迪杰斯特拉算法求有向网G中的V0 定点到其余顶点的最短路径
    int n = G.vexnum;//顶点数
    for (int v = 0; v < n; v++)//n个顶点依次初始化
    {
        S[v] = false;//S初始化为空集
        D[v] = G.arcs[v0][v];//将v0到各个终点的最短路径长度初始化为边上的权值
        if (D[v] < MAX)
            Path[v] = v0;//如果v0和v之间有边,则将v的前驱初始化为v0
        else
            Path[v] = -1;//如果v0和v之间无边,则将v的前驱初始化为-1
    }
    S[v0] = true; //将v0加入s
    D[v0] = 0;//源点到源点的权值为0
    //---------初始化结束,开始主循环,每次求得v0到某个顶点的最短路径,将v加到S数组
    for (int i = 1; i < n; i++)//依次对其余n-1个顶点进行计算
    {
        int    min = MAX;
        int v = v0;
        for (int w = 0; w < n; w++)
        {
            if (!S[w] && D[w] < min)
            {//选择一条当前最短路径,终点为v
                v = w;
                min = D[w];
            }
            S[v] = true;//将v加到s集合中
            for (int w = 0; w < n; w++)
            {//更新从v0出发到集合V-S上所有顶点的最短路径长度
                if (!S[w] && (D[v] + G.arcs[v][w] < D[w]))
                {
                    D[w] = D[v] + G.arcs[v][w];//更新D[w]
                    Path[w] = v;//更改w的前驱为v
                }
            }
        }
    }
}
//背景函数
void backGround()
{
    cout << "|*****************************************************************|" << endl;
    cout << "    |------------------------铁大旅游景点图-----------------|"     << endl;
    cout << "|*****************************************************************|" << endl;
    cout << "|           ⑦                                          单位:米  |" << endl;
    cout << "|           九教                                                  |" << endl;
    cout << "|            ◎                                      ⑧           |" << endl;
    cout << "|           ↗↖                                    九栋          |" << endl;
    cout << "|  ③  200╱    ╲                                   ◎           |" << endl;
    cout << "|  西   ↙        ╲ 150                            ↗ ↖         |" << endl;
    cout << "|  操 ◎            ╲       ①               160 ╱     ╲ 200   |" << endl;
    cout << "|  场  ↖150          ╲    信息          ⑥    ╱         ╲     |" << endl;
    cout << "|    ④  ↘    140      ↘  学院  200    基教 ↙     230     ↘   |" << endl;
    cout << "|   体育馆 ◎-------------→◎←--------------→◎←--------------→◎ |" << endl;
    cout << "|            ↖         ↗ ↖              ↗ ↖             ↗② |" << endl;
    cout << "|          100 ╲     ╱     ╲ 125      ╱     ╲ 150     ╱  综 |" << endl;
    cout << "|                ↘ ↙ 100     ╲      ╱135      ╲     ╱145 餐 |" << endl;
    cout << "|                  ◎            ↘  ↙             ↘ ↙        |" << endl;
    cout << "|             ⑨ 沁园              ◎                 ◎         |" << endl;
    cout << "|                             ⑩ 翠园          ⑤  春晖楼         |" << endl;
    cout << "|                                                               |" << endl;
    cout << "|*****************************************************************|" << endl;

}
//主菜单
void menu()
{
    cout << "|*****************************************************************|" << endl;
    cout << "|----------------------------铁大导游小程序-----------------------|" << endl;
    cout << "    |*********************************************************|" << endl;
    cout << "        |--------------------1-景点信息查询--------------|" << endl;
    cout << "        |--------------------2-最短路径查询--------------|" << endl;
    cout << "        |--------------------3-显示景点视图--------------|" << endl;
    cout << "        |-------------------4-退出导游程序------ --------|" << endl;
    cout << "|*****************************************************************|" << endl;
    cout << ">>>请选择:";
}
//景点信息查询二级菜单
void jmenu()
{
    cout << "|*****************************************************************|" << endl;
    cout << "    |-------------------------景点信息查询------------------------|" << endl;
    cout << "    |***********************************************************|" << endl;
    cout << "      |----------------------1-信息学院介绍-------------------| " << endl;
    cout << "      |----------------------2-综合餐厅介绍-------------------| " << endl;
    cout << "      |----------------------3-西操场介绍---------------------| " << endl;
    cout << "      |----------------------4-体育馆介绍---------------------| " << endl;
    cout << "      |----------------------5-春晖楼介绍---------------------| " << endl;
    cout << "      |----------------------6-基教介绍-----------------------| " << endl;
    cout << "      |----------------------7-九教介绍-----------------------| " << endl;
    cout << "      |----------------------8-九栋介绍-----------------------| " << endl;
    cout << "      |----------------------9-沁园介绍-----------------------| " << endl;
    cout << "      |---------------------10-翠园介绍-----------------------| " << endl;
    cout << "|*****************************************************************|" << endl;
    cout << ">>>请要查询的景点编号:";
}
//最短路径查询二级菜单
void pmenu() { cout << "|*****************************************************************|" << endl; cout << " |-------------------------最短路径查询------------------------|" << endl; cout << " |***********************************************************|" << endl; cout << " |---------------------1-信息学院-------------------| " << endl; cout << " | --------------------2-综合餐厅-------------------| " << endl; cout << " |---------------------3-西操场---------------------| " << endl; cout << " |---------------------4-体育馆---------------------| " << endl; cout << " |---------------------5-春晖楼---------------------| " << endl; cout << " |---------------------6-基教-----------------------| " << endl; cout << " |---------------------7-九教-----------------------| " << endl; cout << " |---------------------8-九栋-----------------------| " << endl; cout << " |---------------------9-沁园-----------------------| " << endl; cout << " |--------------------10-翠园-----------------------| " << endl; cout << "|*****************************************************************|" << endl; cout << ">>>请依次输入起点编号和终点编号:"; } void main() { //初始化操作 AMGraph amg = { { "信息学院","综合餐厅","西操场","体育馆","春晖楼", "基教", "九教", "九栋", "沁园", "翠园" }, //-1代表两边不相连,权值无限大 //邻接矩阵 /* 信 综 西 体 春 基 教 栋 沁 翠*/ {{MAX,MAX,MAX,140,MAX,200,150,MAX,100,125 }, {MAX,MAX,MAX,MAX,145,230,MAX,100,MAX,MAX }, {MAX,MAX,MAX,150,MAX,MAX,200,MAX,MAX,MAX }, {140,MAX,150,MAX,MAX,MAX,MAX,MAX,100,MAX }, {MAX,145,MAX,MAX,MAX,150,MAX,MAX,MAX,MAX }, {200,230,MAX,MAX,150,MAX,MAX,160,MAX,135 }, {150,MAX,200,MAX,MAX,MAX,MAX,MAX,MAX,MAX }, {MAX,200,MAX,MAX,MAX,160,MAX,MAX,MAX,MAX }, {100,MAX,MAX,100,MAX,MAX,MAX,MAX,MAX,MAX }, {125,MAX,MAX,MAX,MAX,135,MAX,MAX,MAX,MAX } },10,14}; int f, ff; int start, end; while (true) { cout << endl; menu(); cin >> f; if (f == 1) { jmenu(); cin >> ff;
       //景点信息从文件中读取 ifstream outfile(
"schooltravel.txt", ios :: out | ios :: binary); if (!outfile) { cerr << "读取景点介绍文件失败!" << endl; exit(1); } string str[max]; int i = 0; while (getline(outfile, str[i++])); cout << "|-----------------------景点介绍-------------------| " << endl; if (ff == 1) cout << str[0] << endl; else if (ff == 2) cout << str[1] << endl; else if (ff == 3) cout << str[2] << endl; else if(ff == 4) cout << str[3] << endl; else if (ff == 5) cout << str[4] << endl; else if (ff == 6) cout << str[5] << endl; else if (ff == 7) cout << str[6] << endl; else if (ff == 8) cout << str[7] << endl; else if (ff == 9) cout << str[8] << endl; else if (ff == 10) cout << str[9] << endl; cout << "|-------------------------------------------------|" << endl; } else if (f == 2) { pmenu(); cin >> start >> end; ShortestPath_DIJ(amg, start - 1); int temp = end-1; int temp1, temp2; int flag[max], m = 0; cout << "" << amg.vexs[start - 1] << "" << amg.vexs[end - 1] << "最短路径为:" ; while (temp!= -1) { flag[m++] = temp; temp1 = temp ; temp2 = Path[temp1]; temp = temp2; } for (int i = m-1; i >= 0; i--) { cout <<amg.vexs[flag[i]] << "->"; } cout << endl; cout << "最短路径值为:" << D[end - 1] <<""<< endl; } else if (f == 3) { backGround(); } else if (f == 4) { cout << ">>>退出成功!" << endl; exit(0); } } }

 

  (4)运行截图:

                                 

                                       

                                   

schooltravel.txt下载地址https://files.cnblogs.com/files/dmego/schooltravel.rar

目录
相关文章
|
4月前
|
存储 监控 算法
基于 C++ 哈希表算法实现局域网监控电脑屏幕的数据加速机制研究
企业网络安全与办公管理需求日益复杂的学术语境下,局域网监控电脑屏幕作为保障信息安全、规范员工操作的重要手段,已然成为网络安全领域的关键研究对象。其作用类似网络空间中的 “电子眼”,实时捕获每台电脑屏幕上的操作动态。然而,面对海量监控数据,实现高效数据存储与快速检索,已成为提升监控系统性能的核心挑战。本文聚焦于 C++ 语言中的哈希表算法,深入探究其如何成为局域网监控电脑屏幕数据处理的 “加速引擎”,并通过详尽的代码示例,展现其强大功能与应用价值。
99 2
|
5月前
|
存储 算法 C++
Windows共享文件:探秘C++实现的B树索引算法奇境
在数字化时代,Windows共享文件的高效管理至关重要。B树算法以其自平衡多路搜索特性,在文件索引与存储优化中表现出色。本文探讨B树在Windows共享文件中的应用,通过C++实现具体代码,展示其构建文件索引、优化数据存储的能力,提升文件检索效率。B树通过减少磁盘I/O操作,确保查询高效,为企业和个人提供流畅的文件共享体验。
|
6月前
|
存储 负载均衡 算法
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
165 15
|
6月前
|
运维 监控 算法
解读 C++ 助力的局域网监控电脑网络连接算法
本文探讨了使用C++语言实现局域网监控电脑中网络连接监控的算法。通过将局域网的拓扑结构建模为图(Graph)数据结构,每台电脑作为顶点,网络连接作为边,可高效管理与监控动态变化的网络连接。文章展示了基于深度优先搜索(DFS)的连通性检测算法,用于判断两节点间是否存在路径,助力故障排查与流量优化。C++的高效性能结合图算法,为保障网络秩序与信息安全提供了坚实基础,未来可进一步优化以应对无线网络等新挑战。
|
6月前
|
存储 算法 数据处理
公司局域网管理中的哈希表查找优化 C++ 算法探究
在数字化办公环境中,公司局域网管理至关重要。哈希表作为一种高效的数据结构,通过哈希函数将关键值(如IP地址、账号)映射到数组索引,实现快速的插入、删除与查找操作。例如,在员工登录验证和设备信息管理中,哈希表能显著提升效率,避免传统线性查找的低效问题。本文以C++为例,展示了哈希表在局域网管理中的具体应用,包括设备MAC地址与IP分配的存储与查询,并探讨了优化哈希函数和扩容策略,确保网络管理高效准确。
|
2月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
63 0
|
3月前
|
存储 机器学习/深度学习 算法
基于 C++ 的局域网访问控制列表(ACL)实现及局域网限制上网软件算法研究
本文探讨局域网限制上网软件中访问控制列表(ACL)的应用,分析其通过规则匹配管理网络资源访问的核心机制。基于C++实现ACL算法原型,展示其灵活性与安全性。文中强调ACL在企业与教育场景下的重要作用,并提出性能优化及结合机器学习等未来研究方向。
90 4
|
4月前
|
监控 算法 数据处理
基于 C++ 的 KD 树算法在监控局域网屏幕中的理论剖析与工程实践研究
本文探讨了KD树在局域网屏幕监控中的应用,通过C++实现其构建与查询功能,显著提升多维数据处理效率。KD树作为一种二叉空间划分结构,适用于屏幕图像特征匹配、异常画面检测及数据压缩传输优化等场景。相比传统方法,基于KD树的方案检索效率提升2-3个数量级,但高维数据退化和动态更新等问题仍需进一步研究。未来可通过融合其他数据结构、引入深度学习及开发增量式更新算法等方式优化性能。
131 17
|
3月前
|
机器学习/深度学习 存储 算法
基于 C++ 布隆过滤器算法的局域网上网行为控制:URL 访问过滤的高效实现研究
本文探讨了一种基于布隆过滤器的局域网上网行为控制方法,旨在解决传统黑白名单机制在处理海量URL数据时存储与查询效率低的问题。通过C++实现URL访问过滤功能,实验表明该方法可将内存占用降至传统方案的八分之一,查询速度提升约40%,假阳性率可控。研究为优化企业网络管理提供了新思路,并提出结合机器学习、改进哈希函数及分布式协同等未来优化方向。
79 0
|
5月前
|
存储 监控 算法
基于 C++ 哈希表算法的局域网如何监控电脑技术解析
当代数字化办公与生活环境中,局域网的广泛应用极大地提升了信息交互的效率与便捷性。然而,出于网络安全管理、资源合理分配以及合规性要求等多方面的考量,对局域网内计算机进行有效监控成为一项至关重要的任务。实现局域网内计算机监控,涉及多种数据结构与算法的运用。本文聚焦于 C++ 编程语言中的哈希表算法,深入探讨其在局域网计算机监控场景中的应用,并通过详尽的代码示例进行阐释。
110 4

热门文章

最新文章