[C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)

1 Dijkstra算法

1.1 算法基本信息

  • 解决问题/提出背景

    • 单源最短路径(在带权有向图中,求从某顶点到其余各顶点的最短路径)
  • 算法思想
    • 贪心算法

      • 按路径长度递增的次序,依次产生最短路径的算法
    • 【适用范围】Dijkstra算法仅适用于【权重为正】的图模型中
  • 时间复杂度
    • O(n^3)
  • 补充说明
    • 亦可应用于【多源最短路径】(推荐:Floyd算法(动态规划,O(n^3)))

      • Dijkstra 时间复杂度:O(n^3)

        1.2 算法描述

  • 1.2.1 求解过程(具体思路)

  • 1.2.2 示例

1.2 编程复现

  • 1> 定义图模型(邻接矩阵表示法)的【基本存储结构体】
# define MaxInt 32767 // 表示极大值 即 ∞ (无穷大)
# define MVNum 100 // 最大顶点数 

typedef int VertexType; // 假设顶点的数据类型为整型

typedef int ArcType; // 假设Vi与Vj之边的权值类型为整型 

typedef struct {
    VertexType vexs[MVNum]; // 顶点表 (存储顶点信息)
    ArcType arcs[MVNum][MVNum]; // 邻接矩阵
    int vexnum,arcnum; // 图的当前顶点数与边数
}AMGraph; // Adjacent Matrix Graph 邻接矩阵图 
  • 2> 定义 Dijkstra 算法的【辅助数据结构体】

bool S[MVNum]; // S[i] 记录从源点V0到终点Vi是否已被确定为最短路径长度  【划分确定与未确定: 跟贪心算法的适用范围(不可取消性)有直接联系】
               // true:表已确定;false:表尚未确定
ArcType D[MVNum]; // D[i] 记录从源点V0到终点Vi的【当前】最短路径【长度】
int Path[MVNum];  // Path[i] 记录从源点V0到终点Vi的【当前】最短路径上【Vi的[直接前驱]的顶点序号】 
  • 3> 初始化(邻接矩阵)带权有向图的图模型
void InitAMGraph(AMGraph &G){
    cout<<"Please Input Vertexs Number:";
    cin>>G.vexnum;
    cout<<"\nPlease Directed Edges Number:";
    cin>>G.arcnum;

    for(int i=0;i<MVNum;i++){
        for(int j=0;j<MVNum;j++){
            if(i!=j){ // 【易错】 初始化<Vi, Vj>时: <Vi,Vj> 路径长度无穷大 (i!=j)
                G.arcs[i][j] = MaxInt;
            } else { //  【易错】 初始化<Vi, Vj>时: <Vi,Vi>【自回环】路径长度为0 (i==i)
                G.arcs[i][j] = 0;
            }
        }
    }
    for(int i=0;i<G.vexnum;i++){
        G.vexs[i] = i;
    }
    cout<<"\nPlease Input All Directed Edges and their Weight now:";
    cout<<"\nDirected Edges(i,j,weight): "<<endl;
    int i,j;
    int weight;
    for(int k=0;k<G.arcnum;k++){
//      cout<<"("<<(k+1)<<") ";
        cin>>i;cin>>j;cin>>weight;
        G.arcs[i][j] = weight;
    }
    cout<<endl;
}
  • 4> Dijkstra算法:求解单源最短路径
void ShortestPath_Dijkstra(AMGraph G, int V0){
    //step1 n个顶点依次初始化
    int n =G.vexnum;
    for(int v=0;v<n;v++){
        S[v] = false;
        D[v] = G.arcs[V0][v];
        if(D[v]<MaxInt){
            Path[v] = V0;
        } else {
            Path[v] = -1;
        }
    }
    //step2 将源点V0划入已确定集合S中
    S[V0] = true;
    D[V0] = 0; // 源点V0到源点V0的最短路径长度必然为0
    //step3 贪心算法策略:
    //          3.1 循环遍历所有结点:
    //              3.2 先确定当前最短路径的终点v;
    //              3.3 然后,将v划入已确定集合S中;
    //              3.4 最后,以利用结点v更新所有尚未确定的结点的最短路径
    int v;
    int min;
    D[G.vexnum] = MaxInt;
    for(int i=1;i<n;i++){//3.1循环遍历所有结点 (即 求从源点V0到图中每一顶点(共计n-1个顶点)的最短路径)
        //3.2 确定当前最短路径的终点v;
        min = MaxInt;
        for(int w=0;w<n;w++){
            if(S[w]==false && D[w]<min){//比本轮循环中,已知的最短路径还短 【易错/易漏】 S[w]==false : 必须满足当前结点 Vw 属于尚未确定的结点
                v = w;
                min = D[w];
            }
        }
        //3.3 然后,将v划入已确定集合S中;
        S[v] = true;
        //3.4 最后,以利用结点v更新所有尚未确定的结点的最短路径
        for(int w=0;w<n;w++){
            //↓更新Vw结点的最短路径长度为 D[v] + G.arcs[v][w]
            //cout<<"S["<<w<<"]:"<<S[w]<<"D["<<v<<"]"<<D[v]<<"G.arcs["<<v<<"]["<<w<<"]"<<"D["<<w<<"]"<<D[w]<<endl;
            if(S[w]==false && (D[v] + G.arcs[v][w] < D[w])){//【易错/易漏】 S[w]==false : 必须满足当前结点 Vw 属于尚未确定的结点
                D[w] = D[v] + G.arcs[v][w];
                Path[w] = v; // 更新 结点Vw的前驱为 v
            }
        }
        v = G.vexnum;
    }
}
  • 5> 输出结果 D[i]、Path[j]
void OutputD(AMGraph G, int V0){
    cout<<"Shortest Distance Weight of the Pair of Directed Vertices("<<V0<<", j):"<<endl;
    for(int j=0;j<G.vexnum;j++){
        cout<<D[j]<<"\t";
    }
    cout<<endl;
}

void OutputPath(AMGraph G,int V0){
    cout<<"Shortest Distance Path("<<V0<<",j) of the Pair of Directed Vertices:"<<endl;
    for(int j=0;j<G.vexnum;j++){
        cout<<Path[j]<<"\t";
    }
    cout<<endl;
}
  • 6> 执行:Main函数
int main(){
    int V0; //源点V0的下标
    AMGraph G;
    InitAMGraph(G);

    cout<<"Please Input the Index of Source Node 'V0':";
    cin>>V0;
    ShortestPath_Dijkstra(G, V0);
    OutputD(G, V0);
    OutputPath(G, V0);
    return 0;
}
  • 7> Test: Output of Main

Please Input Vertexs Number:6

Please Directed Edges Number:8

Please Input All Directed Edges and their Weight now:
Directed Edges(i,j,weight):
1 2 5
0 2 10
3 5 10
4 3 20
0 4 30
2 3 50
4 5 60
0 5 100

Please Input the Index of Source Node 'V0':0

Shortest Distance Weight of the Pair of Directed Vertices(0, j):
0       32767   10      50      30      60

Shortest Distance Path(0,j) of the Pair of Directed Vertices:
0       -1      0       4       0       3

2 参考文献

  • 《数据结构(C语言版/ 严蔚敏 李冬梅 吴伟民 编)》

原文地址:https://www.cnblogs.com/johnnyzen/p/11613609.html

时间: 2024-10-07 05:28:46

[C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)的相关文章

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法 本篇名言:"辛勤的蜜蜂永没有时间悲哀.--布莱克" 这次来看下Dijkstra )算法.还是老方法,先原理,后实现.代码来自网络. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47046031 1.  最短路径 最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径. 管道铺设.线路安排

最短路径---迪杰斯特拉算法[图中一个顶点到其他顶点的最短距离]

转自大神:https://www.cnblogs.com/skywang12345/p/3711512.html 是真的牛逼 看大神的吧 舒服点  我注释了点最后代码的部分 迪杰斯特拉算法介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用

[从今天开始修炼数据结构]图的最短路径 —— 迪杰斯特拉算法和弗洛伊德算法的详解与Java实现

在网图和非网图中,最短路径的含义不同.非网图中边上没有权值,所谓的最短路径,其实就是两顶点之间经过的边数最少的路径:而对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,我们称路径上第一个顶点是源点,最后一个顶点是终点. 我们讲解两种求最短路径的算法.第一种,从某个源点到其余各顶点的最短路径问题. 1,迪杰斯特拉(Dijkstra)算法 迪杰斯特拉算法是一个按路径长度递增的次序产生最短路径的算法,每次找到一个距离V0最短的点,不断将这个点的邻接点加入判断,更新新加入的点到V0的距

数据结构图之三(最短路径--迪杰斯特拉算法——转载自i=i++

数据结构图之三(最短路径--迪杰斯特拉算法) [1]最短路径 最短路径?别乱想哈,其实就是字面意思,一个带边值的图中从某一个顶点到另外一个顶点的最短路径. 官方定义:对于内网图而言,最短路径是指两顶点之间经过的边上权值之和最小的路径. 并且我们称路径上的第一个顶点为源点,最后一个顶点为终点. 由于非内网图没有边上的权值,所谓的最短路径其实是指两顶点之间经过的边数最少的路径. 别废话了!整点实际的哈,你能很快计算出下图中由源点V0到终点V8的最短路径吗? [2]迪杰斯特拉算法 迪杰斯特拉算法是按路

最短路径 - 迪杰斯特拉(Dijkstra)算法

对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法.本文先来讲第一种,从某个源点到其余各顶点的最短路径问题. 这是一个按路径长度递增的次序产生最短路径的算法,它的大致思路是这样的. 比如说要求图7-7-3中顶点v0到v1的最短路径,显然就是1.由于顶点v1还与v2,v3,v4连线,所以此时我们同时求得了v0->v1->v2 = 1+3 =

C# 迪杰斯特拉(Dijkstra)算法

Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合.一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知. 初始时,S中仅含有源.设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度.Dijkstra算法每次从V-S中取出具有最短特殊路长度

迪杰斯特拉(Dijkstra)算法

1 # include <stdio.h> 2 3 # define MAX_VERTEXES 20//最大顶点数 4 # define INFINITY 65535;//代表∞ 5 6 typedef struct 7 {/* 无向图结构体 */ 8 int vexs[MAX_VERTEXES];//顶点下标 9 int arc[MAX_VERTEXES][MAX_VERTEXES];//矩阵 10 int numVertexes, numEdges;//顶点数和边数 11 12 }MGra

迪杰斯特拉(Dijkstra)算法求最短路径

我用的是邻接矩阵来存储图的. 代码如下: void Graph:: Dijkstra(){ struct DijNode{ int index; int distance; vector<string> path; bool Founded; //判定是否找到了... }; DijNode*shorestPaths=new DijNode[mgraph.vexnum]; string startPoint; int startIndex; cout<<"请输入单源点:&q

迪杰斯特拉/dijkstra 算法模板(详细注释)

#include <iostream> #include <malloc.h> #include <cstring> #include <stack> #include <cstdio> //定义邻接矩阵的大小 #define N 100 #define M 100 using namespace std; typedef struct node { int map[N][M];//邻接矩阵 int n;//顶点数 int e;//边数 }MGr