图->最短路径->单源最短路径(迪杰斯特拉算法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实现
在网图和非网图中,最短路径的含义不同.非网图中边上没有权值,所谓的最短路径,其实就是两顶点之间经过的边数最少的路径:而对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,我们称路径上第 ...
随机推荐
- Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -
mysql -A不预读数据库信息(use dbname 更快)—Reading table information for completion of table and column names Y ...
- Linux内核剖析(三)构建源码树
linux源码树结构 参考 http://www.360doc.com/content/13/0410/17/7044580_277403053.shtml 目录 描述 arch 目录包括了所有和体系 ...
- mac关闭占用某个端口的进程
在启动项目的时候有时候会提示端口被占用,但是怎么都找不到那个关闭进程的地方,可以直接通过命令行关闭这个进程: 比如要关闭:8000端口的进程: 1. 查找端口进程: lsof -i: 会把所有的占用8 ...
- Jquery on方法绑定事件后执行多次
每次绑定前先取消上次的绑定. $('#sub').unbind('click').click(function () { ... });
- pyCoreImage Learn
目录 PyCoreImage 安装 高斯模糊滤镜的例子 使用详细步骤说明 常见操作 滤镜操作 打印所有的滤镜列表 打印某个滤镜的详细信息 使用 zoomBlur 滤镜 使用 mono 滤镜 使用叠加率 ...
- tun/tap设备_虚拟网卡
tun/tap 驱动程序实现了虚拟网卡的功能,tun表示虚拟的是点对点设备,tap表示虚拟的是以太网设备,这两种设备针对网络包实施不同的封装.利用tun/tap 驱动,可以将tcp/ip协议栈处理好的 ...
- 【转】WPF自定义控件与样式(11)-等待/忙/正在加载状态-控件实现
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要有三种实现方式: 简单忙碌状态控件BusyBox: Win8/win10效果忙 ...
- Vue+Vue-router微信分享功能
在使用vue和vue-router路由框架已经开发过好几个项目了,其中也遇到不少坑,有些坑各种搜也没有找到非常理想的答案. vue学习相对来说还是比较简单,官方文档说明非常清楚(https://cn. ...
- miniprogrampatch 提供 watch 和 computed 特性
推荐一个小程序补丁 github:miniprogrampatch,为你的 Page 和 Component 增加 watch 和 computed 特性. 安装 通过 npm 安装:npm inst ...
- java基础---->String中的split方法的原理
这里面主要介绍一下关于String类中的split方法的使用以及原理. split函数的说明 split函数java docs的说明: When there is a positive-width m ...