文字描述

  引言:如下图一个交通系统,从A城到B城,有些旅客可能关心途中中转次数最少的路线,有些旅客更关心的是节省交通费用,而对于司机,里程和速度则是更感兴趣的信息。上面这些问题,都可以转化为求图中,两顶点最短带权路径的问题。

  单源点的最短路径问题: 给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径。迪杰斯特拉(Dijkstra)提出了一个按路径长度递增的次序产生最短路径的算法。迪杰斯特拉(Dijkstra)算法描述如下:

  

示意图

  

  

  

算法分析

  结合代码实现部分分析这个算法的运行时间。本博客写的代码,其时间复杂度为n^3, 但是理论上应该只为n^2

代码实现

 //
// Created by lady on 19-1-3.
//
#include <stdio.h>
#include <stdlib.h> #define INFINITY 100000 //最大值
#define MAX_VERTEX_NUM 20 //最大顶点数
typedef enum {DG, DN, UDG, UDN} GraphKind; //{有向图,有向网,无向图,无向网}
typedef struct ArcCell{
int weight; //该弧相关信息的指针
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM], PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM], ShortPathTable[MAX_VERTEX_NUM];
typedef struct VertexType{
char data[];
}VertexType;
typedef struct{
VertexType vexs[MAX_VERTEX_NUM]; //顶点向量
AdjMatrix arcs; //邻接矩阵
int vexnum, arcnum; //图的当前顶点数和弧数
GraphKind kind; //图的种类标志
}MGraph; /*
* 根据顶点信息, 返回该顶点在图中的位置, 如果返回-1表示顶点不存在
*/
static int LocateVex(MGraph *G, char data[])
{
int i = ;
for(i=; i<G->vexnum; i++){
if(!strncmp(G->vexs[i].data, data, strlen(G->vexs[i].data))){
return i;
}
}
return -;
} /*
* 用邻接矩阵作为存储结构,创建有向网
*/
static int CreateGraphDN(MGraph *G)
{
printf("用邻接矩阵创建有向网,输入顶点数,弧数:");
G->kind = DN;
scanf("%d,%d", &G->vexnum, &G->arcnum);
if(G->vexnum > MAX_VERTEX_NUM){
printf("错误:顶点数不能超过%d!!\n", MAX_VERTEX_NUM);
return -;
}
int i = , j = , k = ;
char v1[] = {}, v2[]={}, info[] = {};
char tmp[] = {};
for(i=; i<G->vexnum; i++){
printf("输入第%d个顶点: ", i);
memset(G->vexs[i].data, , sizeof(G->vexs[].data));
scanf("%s", G->vexs[i].data);
for(j=; j<G->vexnum; j++){
G->arcs[i][j].weight = INFINITY;
}
G->arcs[i][i].weight = ;
}
for(k=; k<G->arcnum; k++){
printf("输入第%d条弧(顶点1, 顶点2): ", k);
memset(tmp, , sizeof(tmp));
scanf("%s", tmp);
sscanf(tmp, "%[^','],%[^','],%s[^\\n]", v1, v2, info);
i = LocateVex(G, v1);
j = LocateVex(G, v2);
if(i< || j< || (!atoi(info))){
printf("错误:顶点%s或者%s不存在, 或者权值信息%s不对!\n", v1, v2, info);
return -;
}
G->arcs[i][j].weight = atoi(info);
}
return ;
}
static void printMatrix(int vexnum, VertexType vexs[], int (*arcs)[MAX_VERTEX_NUM])
{
int i = , j = ;
printf("\t");
for(i=; i<vexnum; i++){
printf("%s\t", vexs[i].data);
}
printf("\n");
for(i=; i<vexnum; i++){
printf("%s\t", vexs[i].data);
for(j=; j<vexnum; j++){
if(arcs[i][j] == INFINITY){
printf("INF\t");
}else{
printf("%d\t", arcs[i][j]);
}
}
printf("\n");
}
return ;
} static void printArchs(int vexnum, VertexType vexs[], AdjMatrix arcs)
{
int i = , j = ;
printf("\t");
for(i=; i<vexnum; i++){
printf("%s\t", vexs[i].data);
}
printf("\n");
for(i=; i<vexnum; i++){
printf("%s\t", vexs[i].data);
for(j=; j<vexnum; j++){
if(arcs[i][j].weight == INFINITY){
printf("INF\t");
}else{
printf("%d\t", arcs[i][j].weight);
}
}
printf("\n");
}
return ;
} #include <string.h>
/*
* Dijkstra迪杰斯特拉算法
* 从有向网G的顶点v0出发,求v0到其余顶点v的最短路径P[v]及其带权长度D[v].weight
* 若P[v][w].weight为TRUE(1),则w是从v0到v当前求得最短路径上的顶点。
* final[v]为TRUE(1),当且仅当v属于S,即已经求得从v0到v的最短路径
*/
void ShortestPath_DIJ(MGraph *G, int v0)
{
int v = ;
int w = ;
int i = ;
int j = ;
int final[MAX_VERTEX_NUM] = {};
int min = ;
int P[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
ShortPathTable D; for(v=; v<G->vexnum; ++v){
D[v].weight = G->arcs[v0][v].weight;
//设为空路径
for(w=; w<G->vexnum; ++w){
P[v][w] = ;
}
if(D[v].weight < INFINITY){
P[v][v0] = ;
P[v][v] = ;
}
}
//初始化,v0顶点属于S集
D[v0].weight = ;
final[v0] = ;
//开始主循环,每次求得v0到某个v顶点的最短路径,并加v到s集
//其余G->vexnum-1个顶点
for(i=; i<G->vexnum; ++i){
//min存放当前离v0顶点最短的距离
min = INFINITY;
for(w=; w<G->vexnum; w++){
if(!final[w]){
//顶点w在V-S中
if(D[w].weight < min){
//顶点v0更近
min = D[w].weight;
v = w;
}
}
}
if(min == INFINITY)
break;
//离v0最短的顶点v加入S集合
final[v] = ;
//更新当前最短路径和距离
for (w = ; w < G->vexnum; w++) {
if (!final[w] && (min + G->arcs[v][w].weight < D[w].weight)) {
//修改D[w]和P[w],w属于V-S
D[w].weight = min + G->arcs[v][w].weight;
for(j=; j<G->vexnum; j++){
P[w][j] = P[v][j];
}
P[w][w] = ;
}
}
} printf("\n打印最短路径:\n");
printMatrix(G->vexnum, G->vexs, P); printf("\n打印%s到其余顶点的带权长度:\n", G->vexs[v0].data);
for(i=; i<G->vexnum; i++){
if(D[i].weight == INFINITY){
printf("%s,INF\t", G->vexs[i].data);
}else {
printf("%s,%d\t", G->vexs[i].data, D[i].weight);
}
}
printf("\n");
return ;
} int main(int argc, char *argv[])
{
//以邻接矩阵为存储结构创建有向网
MGraph G;
if(CreateGraphDN(&G) < ){
return -;
}
printf("\n打印该图中的信息:\n");
printArchs(G.vexnum, G.vexs, G.arcs);
//Dijkstra迪杰斯特拉算法求单源最短路径
ShortestPath_DIJ(&G, );
return ;
}

单源最短路径(Dijkstra)

代码运行

/home/lady/CLionProjects/untitled/cmake-build-debug/untitled
用邻接矩阵创建有向网,输入顶点数,弧数:6,8
输入第0个顶点: v0
输入第1个顶点: v1
输入第2个顶点: v2
输入第3个顶点: v3
输入第4个顶点: v4
输入第5个顶点: v5
输入第0条弧(顶点1, 顶点2): v0,v5,100
输入第1条弧(顶点1, 顶点2): v0,v4,30
输入第2条弧(顶点1, 顶点2): v0,v2,10
输入第3条弧(顶点1, 顶点2): v1,v2,5
输入第4条弧(顶点1, 顶点2): v2,v3,50
输入第5条弧(顶点1, 顶点2): v4,v5,60
输入第6条弧(顶点1, 顶点2): v4,v3,20
输入第7条弧(顶点1, 顶点2): v3,v5,10 打印该图中的信息:
v0 v1 v2 v3 v4 v5
v0 0 INF 10 INF 30 100
v1 INF 0 5 INF INF INF
v2 INF INF 0 50 INF INF
v3 INF INF INF 0 INF 10
v4 INF INF INF 20 0 60
v5 INF INF INF INF INF 0 打印最短路径:
v0 v1 v2 v3 v4 v5
v0 1 0 0 0 0 0
v1 0 0 0 0 0 0
v2 1 0 1 0 0 0
v3 1 0 0 1 1 0
v4 1 0 0 0 1 0
v5 1 0 0 1 1 1 打印v0到其余顶点的带权长度:
v0,0 v1,INF v2,10 v3,50 v4,30 v5,60 Process finished with exit code 0

图->最短路径->单源最短路径(迪杰斯特拉算法Dijkstra)的更多相关文章

  1. 迪杰斯特拉算法(Dijkstra) (基础dij+堆优化) BY:优少

    首先来一段百度百科压压惊... 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最 ...

  2. 迪杰斯特拉算法dijkstra(可打印最短路径)

    #include <iostream> #include <iomanip> #include <string> using namespace std; #def ...

  3. C# 迪杰斯特拉算法 Dijkstra

    什么也不想说,现在直接上封装的方法: using System; using System.Collections.Concurrent; using System.Collections.Gener ...

  4. dijkstra算法(迪杰斯特拉算法)

    dijkstra算法(迪杰斯特拉算法) 用途:有向图最短路径问题 定义:迪杰斯特拉算法是典型的算法,一般的表述通常有两种方式,这里均采用永久和临时标号的方式,该算法要求图中不存在负权边 用永久和临时标 ...

  5. 单源最短路径-迪杰斯特拉算法(Dijkstra's algorithm)

    Dijkstra's algorithm 迪杰斯特拉算法是目前已知的解决单源最短路径问题的最快算法. 单源(single source)最短路径,就是从一个源点出发,考察它到任意顶点所经过的边的权重之 ...

  6. 单源最短路径算法——Dijkstra算法(迪杰斯特拉算法)

    一 综述 Dijkstra算法(迪杰斯特拉算法)主要是用于求解有向图中单源最短路径问题.其本质是基于贪心策略的(具体见下文).其基本原理如下: (1)初始化:集合vertex_set初始为{sourc ...

  7. c/c++ 图的最短路径 Dijkstra(迪杰斯特拉)算法

    c/c++ 图的最短路径 Dijkstra(迪杰斯特拉)算法 图的最短路径的概念: 一位旅客要从城市A到城市B,他希望选择一条途中中转次数最少的路线.假设途中每一站都需要换车,则这个问题反映到图上就是 ...

  8. 图(最短路径算法————迪杰斯特拉算法和弗洛伊德算法).RP

    文转:http://blog.csdn.net/zxq2574043697/article/details/9451887 一: 最短路径算法 1. 迪杰斯特拉算法 2. 弗洛伊德算法 二: 1. 迪 ...

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

    在网图和非网图中,最短路径的含义不同.非网图中边上没有权值,所谓的最短路径,其实就是两顶点之间经过的边数最少的路径:而对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,我们称路径上第 ...

随机推荐

  1. Cocoapods pod update执行失败报错CocoaPods was not able to update the `master` repo.2019的解决

    很久没动pod,最近更新发现: CocoaPods报CocoaPods was not able to update the `master` repo. If this is an unexpect ...

  2. CentOS7为php7.2安装php-redis扩展

    先下载phpredis-develop cd /tmpwget https://codeload.github.com/phpredis/phpredis/zip/develop 安装unzip.zi ...

  3. Mobile 抓包,代理

    Mobile代理,抓包工具 Fiddler 下载链接, 适用于Win平台.免费: Charles, 下载链接, 使用与MAC平台,收费,有30天的免费使用期,重新下载安装可以再次获得30天的免费使用时 ...

  4. sshpass 实现shell脚本直接加载密登录服务器

    主要命令:sshpass 这个命不是系统自带的,需要安装: # which sshpass/usr/bin/sshpass[root@666 tools]# rpm -qf /usr/bin/sshp ...

  5. node出现 Error: listen EACCES 0.0.0.0:8080错误

    Error: listen EACCES 0.0.0.0:8080 at Object._errnoException (util.js:1022:11) at _exceptionWithHostP ...

  6. spring gateway 截取response 长度缺失

    网上找到一段获取修改response的代码:https://blog.csdn.net/tianyaleixiaowu/article/details/83618037 代码如下: import or ...

  7. rpc error: code = Internal desc = stream terminated by RST_STREAM with error code: PROTOCOL_ERROR

    使用grpc-go调用grpc服务端时,出现rpc error: code = Internal desc = stream terminated by RST_STREAM with error c ...

  8. 教你如何让数据库支持emoji表情符存储

    From: http://www.cnblogs.com/janehoo/archive/2016/04/06/5359800.html 一.教你如何让数据库支持emoji表情符存储 解决方式:更换字 ...

  9. NuGet Packages are missing,This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.

    错误内容 This project references NuGet package(s) that are missing on this computer. Use NuGet Package R ...

  10. java如何对List集合中的元素进行排序(请收藏)

    在java开发中有时候我们需要对List集合中的元素按照一定的规则进行排序,比如说有个Person的集合,我们要根据Person的age属性进行排序输出,这就需要用到Java中提供的对集合进行操作的工 ...