最短路径:Dijkstra算法(求单源最短路径)Floyd算法(求各顶点之间最短路径)[通俗易懂]

最短路径:Dijkstra算法(求单源最短路径)Floyd算法(求各顶点之间最短路径)[通俗易懂]最短路径:在一个带权图中,顶点V0到图中任意一个顶点Vi的一条路径所经过边上的权值之和,定义为该路径的带权路径长度,把带权路径最短的那条路径称为最短路径。DiskStra算法:求单源最短路径,即求一个顶点到任意顶点的最短路径,其时间复杂度为O(V*V)如图所示:求顶点0到各顶点之间的最短路径代码实现:#include<stdio.h>#include&l…

大家好,又见面了,我是你们的朋友全栈君。

最短路径:

在一个带权图中,顶点V0到图中任意一个顶点Vi的一条路径所经过边上的权值之和,定义为该路径的带权路径长度,把带权路径最短的那条路径称为最短路径。

DiskStra算法:

求单源最短路径,即求一个顶点到任意顶点的最短路径,其时间复杂度为O(V*V)

最短路径:Dijkstra算法(求单源最短路径)Floyd算法(求各顶点之间最短路径)[通俗易懂]

如图所示:求顶点0到各顶点之间的最短路径

代码实现:

#include<stdio.h>
#include<stdlib.h>
#define MaxVexNum 50
#define MaxInt 32767
#define MaxEdgeNum 50
//邻接矩阵
typedef int VertexType;
typedef int EdgeType;
typedef struct AMGraph{
	VertexType vexs[MaxVexNum];//顶点表 
	EdgeType arcs[MaxVexNum][MaxVexNum];//邻接矩阵表 
	int vexnum,edgenum;//顶点数,边数 
}AMGraph; 

void createGraph(AMGraph &g){//创建无向图 
	printf("请输入顶点数:");
	scanf("%d",&g.vexnum);
	printf("\n请输入边数:");
	scanf("%d",&g.edgenum);
	
	//初始化顶点表 
	for(int i=0;i<g.vexnum;i++){
		g.vexs[i]=i; 
	} 
	for(int i=0;i<g.vexnum;i++){
		for(int j=0;j<g.vexnum;j++){
			g.arcs[i][j]=MaxInt;
			if(i==j) g.arcs[i][j]=0;
		}
	} 
	printf("请输入边的信息以及边的权值(顶点是0~n-1)\n");
	for(int i=0;i<g.edgenum;i++){
		int x,y,w;
		scanf("%d%d%d",&x,&y,&w);
		g.arcs[x][y]=w;
		//g.arcs[y][x]=w;
	}
}
void PrintGraph(AMGraph g){
	printf("邻接矩阵为:\n");
	for(int i=0;i<g.vexnum;i++) {
		printf("  %d",g.vexs[i]);
	}
	printf("\n");
	for(int i=0;i<g.vexnum;i++){
		printf("%d ",g.vexs[i]);
		for(int j=0;j<g.vexnum;j++){
			if(g.arcs[i][j]==32767){
				printf("∞ "); 
			}else{
				printf("%d  ",g.arcs[i][j]);
			}	
		}
		printf("\n");
	} 
}
//Dijkstra算法,求单源最短路径
void Dijkstra(AMGraph g,int dist[],int path[],int v0){
	int n=g.vexnum,v;
	int set[n];//set数组用于记录该顶点是否归并 
	//第一步:初始化 
	for(int i=0;i<n;i++){
		set[i]=0;
		dist[i]=g.arcs[v0][i];
		if(dist[i]<MaxInt){//若距离小于MaxInt说明两点之间有路可通 
			path[i]=v0;//则更新路径i的前驱为v 
		}else{
			path[i]=-1; //表示这两点之间没有边
		 } 
	}
	set[v0]=1;//将初始顶点并入 
	path[v0]=-1;//初始顶点没有前驱
	
	//第二步 
	for(int i=1;i<n;i++){//共n-1个顶点 
		int min=MaxInt;
		//第二步:从i=1开始依次选一个距离顶点的最近顶点 
		for(int j=0;j<n;j++){
			if(set[j]==0&&dist[j]<min){
				v=j;
				min=dist[j];
		}
	}
	//将顶点并入 
	set[v]=1;	
	//第三步:在将新结点并入后,其初始顶点v0到各顶点的距离将会发生变化,所以需要更新dist[]数组
	for(int j=0;j<n;j++){
		if(set[j]==0&&dist[v]+g.arcs[v][j]<dist[j]){
			dist[j]=dist[v]+g.arcs[v][j];
			path[j]=v;
		}
	} 	
 } 
 //输出 
 printf("       ");
 for(int i=0;i<n;i++) printf("%d  ",i);
  
 printf("\ndist[]:");
 for(int i=0;i<n;i++) printf("%d  ",dist[i]);
 
 printf("\npath[]:");
 for(int i=0;i<n;i++) printf("%d  ",path[i]);

}

int main(){
	AMGraph g;
	createGraph(g);
	int dist[g.vexnum];
	int path[g.vexnum];
	Dijkstra(g,dist,path,0);
} 

最短路径:Dijkstra算法(求单源最短路径)Floyd算法(求各顶点之间最短路径)[通俗易懂]

Floyd算法:

求各顶点之间的最短路径,其时间复杂度为O(V*V*V)

最短路径:Dijkstra算法(求单源最短路径)Floyd算法(求各顶点之间最短路径)[通俗易懂]

如图所示,求<1,0>之间的最短路径:

代码实现:

#include<stdio.h>
#include<stdlib.h>
#define MaxVexNum 50
#define MaxInt 32767
#define MaxEdgeNum 50
//邻接矩阵
typedef int VertexType;
typedef int EdgeType;
typedef struct AMGraph{
	VertexType vexs[MaxVexNum];//顶点表 
	EdgeType arcs[MaxVexNum][MaxVexNum];//邻接矩阵表 
	int vexnum,edgenum;//顶点数,边数 
}AMGraph; 

void createGraph(AMGraph &g){//创建无向图 
	printf("请输入顶点数:");
	scanf("%d",&g.vexnum);
	printf("\n请输入边数:");
	scanf("%d",&g.edgenum);
	
	//初始化顶点表 
	for(int i=0;i<g.vexnum;i++){
		g.vexs[i]=i; 
	} 
	for(int i=0;i<g.vexnum;i++){
		for(int j=0;j<g.vexnum;j++){
			g.arcs[i][j]=MaxInt;
			if(i==j) g.arcs[i][j]=0;
		}
	} 
	printf("请输入边的信息以及边的权值(顶点是0~n-1)\n");
	for(int i=0;i<g.edgenum;i++){
		int x,y,w;
		scanf("%d%d%d",&x,&y,&w);
		g.arcs[x][y]=w;
		//g.arcs[y][x]=w;
	}
}
void PrintGraph(AMGraph g){
	printf("邻接矩阵为:\n");
	for(int i=0;i<g.vexnum;i++) {
		printf("  %d",g.vexs[i]);
	}
	printf("\n");
	for(int i=0;i<g.vexnum;i++){
		printf("%d ",g.vexs[i]);
		for(int j=0;j<g.vexnum;j++){
			if(g.arcs[i][j]==32767){
				printf("∞ "); 
			}else{
				printf("%d  ",g.arcs[i][j]);
			}	
		}
		printf("\n");
	} 
}

//Floyd算法

//递归输出两个顶点直接最短路径 
void printPath(int u,int v,int path[][MaxVexNum]){
	if(path[u][v]==-1){
		printf("[%d %d] ",u,v);
	}else{
		int mid=path[u][v];
		printPath(u,mid,path);
		printPath(mid,v,path);
	}
}
void Floyd(AMGraph g,int path[][MaxVexNum]){
	int n=g.vexnum;
	int A[n][n];
	//第一步:初始化path[][]和A[][]数组 
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			A[i][j]=g.arcs[i][j];
			path[i][j]=-1; 
		}
	}
	//第二步:三重循环,寻找最短路径 
	for(int v=0;v<n;v++){//第一层是代表中间结点 
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				if(A[i][j]>A[i][v]+A[v][j]){
					A[i][j]=A[i][v]+A[v][j];
					path[i][j]=v;
				}
			}
		} 
	} 
} 
 
int main(){
	AMGraph g;
	createGraph(g);
	PrintGraph(g);
	int path[MaxVexNum][MaxVexNum];
	Floyd(g,path);

	printPath(1,0,path);
} 

代码运行截图:

最短路径:Dijkstra算法(求单源最短路径)Floyd算法(求各顶点之间最短路径)[通俗易懂]

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/152181.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 线程的notify方法_forkjoinpool默认线程数量

    线程的notify方法_forkjoinpool默认线程数量从源码角度剖析notify/notifyAll方法到底做了些什么,线程是如何唤醒的。

    2022年9月8日
    0
  • java中的关键字有哪些_java关键字有哪些?java关键字大全

    java中的关键字有哪些_java关键字有哪些?java关键字大全你知道java关键词都有哪些吗?下面小编就对于java关键词做了一次集合的大整理,下面就来和小编一起来了解一下,java的关键词吧!一、什么是java关键字?关键字是电脑语言里事先定义的,有特别意义的标识符。程序员利用关键字来告诉编译器其声明的变量类型、类、方法特性等信息。二、java关键字大全1、abstract-表明类或者成员方法具有抽象属性2、assert-断言,用来进行程序调试3、bool…

    2022年7月7日
    22
  • 3s的基本概念_考研基础知识普及

    3s的基本概念_考研基础知识普及      一、什么是“3S”技术“3S”技术是英文遥感技术(RemoteSenescing  RS)、地理信息系统(GeographicalinformationSystem  GIS)、全球定位系统(GlobalPositioningSystem  GPS)这三种技术名词中最后一个单词字头的统称。二、为什么“3S”技术走到了一起人类有一个梦想,就是想只用一种方法,就把

    2022年8月30日
    0
  • 到底学Python还是Java?一张图PK明白!

    到底学Python还是Java?一张图PK明白!点击上方“程序人生”,选择“置顶公众号”第一时间关注程序猿(媛)身边的故事Java和Python一直都是两种很火很强大的编程语言,对于刚开始起步学习编程的同学来说,会迷惑且最经常问的问题是,我该学Java还是Python,是不是Python容易学,或是应该先学什么编程语言等等这样的问题。作为一名Java程序员,肯定会建议你先学Java,然后再学Python,但如果你问一个

    2022年7月7日
    17
  • doxygen教程_genedoc教程

    doxygen教程_genedoc教程综述 我们在编写代码的时候,最头疼的就属于说明书了,很多代码一边写具体代码,一边写说明书,Doxygen主要解决说明书问题,可以在我们写代码的时候讲注释转化为说明书,Graphviz主要是用于图形展示,htmlhelpworkshop主要使用生成CHM文档。1.Doxygen Doxygen能将程序中的特定批注转换成为说明文件。它可以依据程序本身的结构,将程序中按规范注释的批注经过处理…

    2025年6月13日
    0
  • 如何用纯 CSS 创作条形图,不用任何图表库

    如何用纯 CSS 创作条形图,不用任何图表库

    2021年6月16日
    92

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号