最短路径算法

最短路径算法详解

最短路径算法是指求图中顶点之间最短路径的算法,那么根据是求图中一个顶点到其他顶点之间的最短路径还是求图中任意两个顶点之间的最短路径,可以讲该算法分为Dijkstra算法和floyd算法。Dijkstra算法的核心是贪心思想,先求最短路径,然后在此基础上进行延伸,比较延伸后的路径与初始路径的大小,若小则为最短路径,替换原距离,不断循环n-1次,最终求的单源最短路径;floyd算法是一个固定的方法,即用n阶房阵序列来求解。具体的解释有相应的资料可查。下面是算法:

Dijkstra算法代码:

//图的邻接矩阵表示法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stack>
using namespace std;
#define Max 100
#define Inf 0x1111
typedef char type;
typedef struct Grap{
	type data[Max];
	int value[Max][Max];
	int n,m;
}Grap,*pgrap;
bool visit[Max];
int path[Max];
int dis[Max];
int Located(pgrap g,char ch){
	for(int i=0;i<g->n;i++)
		if(g->data[i]==ch)
			return i;
}
void Creat_grap(pgrap g){
	printf("输入图的顶点数和边数:\n");
	scanf("%d%d",&g->n,&g->m);
	//printf("ksgfdkj\n");
	getchar();
	printf("输入图中的顶点:\n");
	int i,j;
	for(i=0;i<g->n;i++){
		g->data[i]=getchar();
		getchar();
	}
	for(i=0;i<g->n;i++)
		for(j=0;j<g->n;j++)
			g->value[i][j]=Inf;
		printf("请输入图中的边:\n");
		int index1,index2,value;
		char ch1,ch2;
		while(g->m--){
			scanf("%c,%c,%d",&ch1,&ch2,&value);
			getchar();
			index1=Located(g,ch1);
			index2=Located(g,ch2);
			g->value[index1][index2]=value;
			//无向图
			g->value[index2][index1]=value;
		}
}
void Dijkstra(pgrap g,char v0){
	int i,j,k,index=Located(g,v0);
	memset(visit,0,sizeof(visit));
	for(i=0;i<g->n;i++){
	    dis[i]=g->value[index][i];
		path[i]=index;
	}
	visit[index]=1;
	dis[index]=0;
	int Maxint,ind;
	for(i=0;i<g->n-1;i++){
        Maxint=Inf;
		ind=index;
		for(j=0;j<g->n;j++)
			if(!visit[j] && dis[j]<Maxint){
				Maxint=dis[j];
				ind=j;
			}
		visit[ind]=1;
		for(k=0;k<g->n;k++)
			if(!visit[k] && dis[ind]+g->value[ind][k]<dis[k]){
				dis[k]=dis[ind]+g->value[ind][k];
				path[k]=ind;
			}
	}
}
void Show_path(pgrap g,char v0){
	 int temp,i,index=Located(g,v0);
     stack<int> s;
	 for(i=0;i<g->n;i++){
	      if(dis[i]==Inf){
		 printf("无法到达\n");
		 continue;
		  }
		 temp=i;
		 while(temp!=index){
			 s.push(temp);
			 temp=path[temp];
		 }
		 //putchar(g->data[index]);
		 printf("%c: ",g->data[index]);
		 while(!s.empty()){
			 printf("%c ",g->data[s.top()]);
			 s.pop();
		 }
		     printf("权值为:%d\n",dis[i]);
	 }
}
int main(){
	Grap g;
	pgrap p=&g;
	Creat_grap(p);
	Dijkstra(p,'G');
	Show_path(p,'G');
	return 0;
}

测试数据:

6 9
A
B
C
D
E
F
A,B,1
A,C,3
B,D,4
B,C,1
C,D,1
D,E,2
C,E,1
E,F,1
D,F,1
输入图的顶点数和边数:
6 9
输入图中的顶点:
A
B
C
D
E
F
请输入图中的边:
A,B,1
A,C,3
B,D,4
B,C,1
C,D,1
D,E,2
C,E,1
E,F,1
D,F,1
A: 权值为:0
A: B 权值为:1
A: B C 权值为:2
A: B C D 权值为:3
A: B C E 权值为:3
A: B C D F 权值为:4
Press any key to continue
6 8
A
B
C
D
E
F
A,B,1
A,C,3
B,C,2
B,D,4
C,D,6
D,F,7
C,E,5
E,F,6
输入图的顶点数和边数:
6 8
输入图中的顶点:
A
B
C
D
E
F
请输入图中的边:
A,B,1
A,C,3
B,C,2
B,D,4
C,D,6
D,F,7
C,E,5
E,F,6
A: 权值为:0
A: B 权值为:1
A: C 权值为:3
A: B D 权值为:5
A: C E 权值为:8
A: B D F 权值为:12
Press any key to continue 

下面是floyd算法:

//图的邻接矩阵表示法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stack>
using namespace std;
#define Max 100
#define Inf 0x1111
typedef char type;
typedef struct Grap{
	type data[Max];
	int value[Max][Max];
	int n,m;
}Grap,*pgrap;
int path[Max][Max];
int val[Max][Max];
int Located(pgrap g,char ch){
	for(int i=0;i<g->n;i++)
		if(g->data[i]==ch)
			return i;
}
void Creat_grap(pgrap g){
	printf("输入图的顶点数和边数:\n");
	scanf("%d%d",&g->n,&g->m);
	//printf("ksgfdkj\n");
	getchar();
	printf("输入图中的顶点:\n");
	int i,j;
	for(i=0;i<g->n;i++){
		g->data[i]=getchar();
		getchar();
	}
	for(i=0;i<g->n;i++)
		for(j=0;j<g->n;j++)
			g->value[i][j]=Inf;
		printf("请输入图中的边:\n");
		int index1,index2,value;
		char ch1,ch2;
		while(g->m--){
			scanf("%c,%c,%d",&ch1,&ch2,&value);
			getchar();
			index1=Located(g,ch1);
			index2=Located(g,ch2);
			g->value[index1][index2]=value;
			//无向图
			//g->value[index2][index1]=value;
		}
}
void floyd(pgrap g){
	int i,j,k;
	for(i=0;i<g->n;i++)
		for(j=0;j<g->n;j++){
			if(i==j)
				val[i][j]=0;
			else
			    val[i][j]=g->value[i][j];
			path[i][j]=Inf;
		}
	for(i=0;i<g->n;i++)
		for(j=0;j<g->n;j++)
			for(k=0;k<g->n;k++)
				if(val[j][i]+val[i][k]<val[j][k]){
					val[j][k]=val[j][i]+val[i][k];
					path[j][k]=i;
				}
}
void Show_path(pgrap g,int x,int y){
    if(path[x][y]==Inf){
		printf("%c ",g->data[y]);
		return ;
	}
	Show_path(g,x,path[x][y]);
	Show_path(g,path[x][y],y);
}
void P_show_path(pgrap g,char ch1,char ch2){
	int index1=Located(g,ch1);
	int index2=Located(g,ch2);
	printf("%c ",g->data[index1]);
	Show_path(g,index1,index2);
}
int main(){
	Grap g;
	pgrap p=&g;
	Creat_grap(p);
	floyd(p);
	for(int i=0;i<p->n;i++)
		for(int j=0;j<p->n;j++){
	       P_show_path(p,p->data[i],p->data[j]);
		   printf("最短路径权值为:%d\n",val[i][j]);
		}
	return 0;
}

	

			
		

下面是测试数据:

输入图的顶点数和边数:
6 8
输入图中的顶点:
A
B
C
D
E
F
请输入图中的边:
A,B,1
A,C,3
B,C,2
B,D,4
C,D,6
D,F,7
C,E,5
E,F,6
A A 最短路径权值为:0
A B 最短路径权值为:1
A C 最短路径权值为:3
A B D 最短路径权值为:5
A C E 最短路径权值为:8
A B D F 最短路径权值为:12
B A 最短路径权值为:1
B B 最短路径权值为:0
B C 最短路径权值为:2
B D 最短路径权值为:4
B C E 最短路径权值为:7
B D F 最短路径权值为:11
C A 最短路径权值为:3
C B 最短路径权值为:2
C C 最短路径权值为:0
C D 最短路径权值为:6
C E 最短路径权值为:5
C E F 最短路径权值为:11
D B A 最短路径权值为:5
D B 最短路径权值为:4
D C 最短路径权值为:6
D D 最短路径权值为:0
D C E 最短路径权值为:11
D F 最短路径权值为:7
E C A 最短路径权值为:8
E C B 最短路径权值为:7
E C 最短路径权值为:5
E C D 最短路径权值为:11
E E 最短路径权值为:0
E F 最短路径权值为:6
F D B A 最短路径权值为:12
F D B 最短路径权值为:11
F E C 最短路径权值为:11
F D 最短路径权值为:7
F E 最短路径权值为:6
F F 最短路径权值为:0


Terminated with return code 0
Press any key to continue ...

===================
输入图的顶点数和边数:
6 8
输入图中的顶点:
A
B
C
D
E
F
请输入图中的边:
A,B,1
A,C,3
B,C,2
B,D,4
C,D,6
D,F,7
C,E,5
E,F,6
A A 最短路径权值为:0
A B 最短路径权值为:1
A C 最短路径权值为:3
A B D 最短路径权值为:5
A C E 最短路径权值为:8
A B D F 最短路径权值为:12
B A 最短路径权值为:4369
B B 最短路径权值为:0
B C 最短路径权值为:2
B D 最短路径权值为:4
B C E 最短路径权值为:7
B D F 最短路径权值为:11
C A 最短路径权值为:4369
C B 最短路径权值为:4369
C C 最短路径权值为:0
C D 最短路径权值为:6
C E 最短路径权值为:5
C E F 最短路径权值为:11
D A 最短路径权值为:4369
D B 最短路径权值为:4369
D C 最短路径权值为:4369
D D 最短路径权值为:0
D E 最短路径权值为:4369
D F 最短路径权值为:7
E A 最短路径权值为:4369
E B 最短路径权值为:4369
E C 最短路径权值为:4369
E D 最短路径权值为:4369
E E 最短路径权值为:0
E F 最短路径权值为:6
F A 最短路径权值为:4369
F B 最短路径权值为:4369
F C 最短路径权值为:4369
F D 最短路径权值为:4369
F E 最短路径权值为:4369
F F 最短路径权值为:0


Terminated with return code 0
Press any key to continue ...



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值