图->最短路径->单源最短路径(迪杰斯特拉算法Dijkstra)
文字描述
引言:如下图一个交通系统,从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)的更多相关文章
- 迪杰斯特拉算法(Dijkstra) (基础dij+堆优化) BY:优少
首先来一段百度百科压压惊... 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最 ...
- 迪杰斯特拉算法dijkstra(可打印最短路径)
#include <iostream> #include <iomanip> #include <string> using namespace std; #def ...
- C# 迪杰斯特拉算法 Dijkstra
什么也不想说,现在直接上封装的方法: using System; using System.Collections.Concurrent; using System.Collections.Gener ...
- dijkstra算法(迪杰斯特拉算法)
dijkstra算法(迪杰斯特拉算法) 用途:有向图最短路径问题 定义:迪杰斯特拉算法是典型的算法,一般的表述通常有两种方式,这里均采用永久和临时标号的方式,该算法要求图中不存在负权边 用永久和临时标 ...
- 单源最短路径-迪杰斯特拉算法(Dijkstra's algorithm)
Dijkstra's algorithm 迪杰斯特拉算法是目前已知的解决单源最短路径问题的最快算法. 单源(single source)最短路径,就是从一个源点出发,考察它到任意顶点所经过的边的权重之 ...
- 单源最短路径算法——Dijkstra算法(迪杰斯特拉算法)
一 综述 Dijkstra算法(迪杰斯特拉算法)主要是用于求解有向图中单源最短路径问题.其本质是基于贪心策略的(具体见下文).其基本原理如下: (1)初始化:集合vertex_set初始为{sourc ...
- c/c++ 图的最短路径 Dijkstra(迪杰斯特拉)算法
c/c++ 图的最短路径 Dijkstra(迪杰斯特拉)算法 图的最短路径的概念: 一位旅客要从城市A到城市B,他希望选择一条途中中转次数最少的路线.假设途中每一站都需要换车,则这个问题反映到图上就是 ...
- 图(最短路径算法————迪杰斯特拉算法和弗洛伊德算法).RP
文转:http://blog.csdn.net/zxq2574043697/article/details/9451887 一: 最短路径算法 1. 迪杰斯特拉算法 2. 弗洛伊德算法 二: 1. 迪 ...
- [从今天开始修炼数据结构]图的最短路径 —— 迪杰斯特拉算法和弗洛伊德算法的详解与Java实现
在网图和非网图中,最短路径的含义不同.非网图中边上没有权值,所谓的最短路径,其实就是两顶点之间经过的边数最少的路径:而对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,我们称路径上第 ...
随机推荐
- python 奇偶拆分list,python拆分list,得到一个原来list的奇数list,一个原来list的偶数list
需求:现在有一个list ,range_data = ['m', 'M', 'h', 'c', 'X', 'Z', 'A', 'o'] 希望得到两个list, 一个是奇数list =['m', 'h ...
- linux源码安装服务器所需要的一些依赖库(待完善)
apaeche :yum -y install gcc gcc-c++ zlib zlib-devel openssl openssl-devel cmake kernel-devel pcre-de ...
- Metadata GC Threshold导致的full gc分析
gc log 两次full gc 均是Metadata GC导致, OpenJDK -Bit Server VM ( :: by (Red Hat -) Memory: 4k page, physic ...
- 解决Eclipse中“诡异”的错误:找不到或无法加载主类
记录下来遇到的(问题,解决方法),是更有效的解决问题的方式.(原谅我领悟的太晚与懒,从此用更有意义的方法,做一个更有意义的人) 因为遇到了多次,参考同一个方法,原文连接:https://blog.cs ...
- php项目踩到的empty函数的一个坑
报错信息: PHP Fatal error: Can't use function return value in write context in /目录省略.../XXService.php on ...
- 关于Retrofit网络请求URL中含有可变参数的处理
开题:在此默认各位看官对Retrofit.以及Okhttp已经有过一定的了解及应用,所以今天我们不谈基础入门的东西,今天我们谈在Retrofit请求接口管理类中URL参数含有动态参数的处理方式.一般我 ...
- awk使用总结
转载自董的博客 1. 什么是awk awk是Unix/Linux提供的样式扫描与处理工具,非常擅长处理结构化数据和生成表单.与sed 和grep 很相似,但功能却超过大于两者,由于awk具备各种脚本语 ...
- Centos7 Crontab
Centos7 Crontab # 查看crontab -l # 编辑 crontab -e # 重启 service crond restart ccrontab 编写规则 # 分 时 日 月 周 ...
- Elasticsearch Java API的基本使用
说明 在明确了ES的基本概念和使用方法后,我们来学习如何使用ES的Java API. 本文假设你已经对ES的基本概念已经有了一个比较全面的认识. 客户端 你可以用Java客户端做很多事情: 执行标准的 ...
- C# 递归省市区三级树结构
省市区结构 实体 /// <summary> /// 行政区 /// </summary> public class AreaEntity { public int Id { ...