数据结构算法(1) 最小路径

假设这样一个情景:

A、B、C、D、E、F五个地方之间的距离为

AB:10  AE:30  AF:100  BC:5  CD:50  DF:10  ED:20  EF:60

求A点到其余各点的最小距离。

可先画出一个带权有向图

 

首先我有一个最直接的思路,由于在创建图的时候,把不存在的边的权值(即距离)设置为一个较大的数,设为M,那么两个点之间的边数是有限的

比如v0到v1:v0-->v1:M;v0->v2-->v1:10+M;........(太多了,不一一举例)然后求出最小的那条,但是这个想起来很简单,但是在程序设计上是很难实现

的,首先必须要用到循环,有几条边就必须要镶嵌几个循环,时间复杂度庞大。

另一个思路来自:v0到vi之间的最小距离必和v0到vj之间的最小距离相关,即D[i]=(D[j]+{j,i}<D[i])?D[j]+{j,i}:D[i](D[i]表示v0到vi之间的最小距离,vi和vj是点域中中的2点,{j,i}表示vj和vi连线的长度)

具体做法:

建立一个数组储存v0到各点间的最小距离设为D[i](D[i]表示v0到vi间的最短距离),D[i]的起始值是v0与vi直接连接的距离

然后取得每两个点之间的距离{j,i},做下述运算

D[i]=(D[j]+{j,i}<D[i])?D[j]+{j,i}:D[i]

最后得到的矩阵D[i]储存的便是v0到vi之间的最短距离

C语言代码如下所示:

#include<Stdio.h>
#include<stdlib.h>
#include<String.h>
#define INFINITY 100000
#define MAX_VERTEX_NUM 20
#define MAX_ARC_NUM 50

/*MGraph结构体是记录无向图的点与点之间的关系(是否相连)以及无向图的边数和顶点数*/
typedef struct{
	char vexs[MAX_VERTEX_NUM];					//记录顶点
	int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];	//邻接矩阵
	int vexnum,arcnum;							//变数和点数
}MGraph;

/*ShortMatrix数组用来记录起始点到其余各点的最短路径,以及与其他最小路径的关系*/
typedef struct{
	int pre;	//记录该最短路径由第pre条最小路径得到
	int lowcost;//权重
}ShortMatrix[MAX_VERTEX_NUM];
void CreateUDN(MGraph &G);						//创建带权有向图
void PrintUDN(MGraph G);						//输出邻接矩阵
void MiniPath(MGraph G, ShortMatrix minedge,char vo);	//求出最小路径
void PrintPath(MGraph G, ShortMatrix minedge,char vo);	//打印出最小路径
int main(){
	MGraph G;									//定义一个图的变量
	ShortMatrix minedge;
	CreateUDN(G);
	printf("对应矩阵为:\n");
	PrintUDN(G);
	MiniPath(G,minedge,'A');
	printf("最短路径为:\n");
	PrintPath(G,minedge,'A');
	printf("\n");
	return 0;
}
void CreateUDN(MGraph &G){
	int vexnum;
	int arcnum;
	int i,j;
	char vex[MAX_VERTEX_NUM];
	while(scanf("%d%d",&vexnum,&arcnum)!=2||vexnum>MAX_VERTEX_NUM||arcnum>50){
		printf("点数输入有误,请重新输入\n");
	}
	for(i=0;i<vexnum;i++){
		for(j=0;j<vexnum;j++){
			if(i==j)
				G.arcs[i][j]=0;
			else
				G.arcs[i][j]=INFINITY;
		}
	}//初始化邻接矩阵
	scanf("%s",vex);//点集
	while(strlen(vex)!=vexnum){
		printf("输入的点的数目不满足要求,请重新输入点集");
		scanf("%s",vex);
	}
	G.vexnum=vexnum;
	G.arcnum=arcnum;
	strcpy(G.vexs,vex);
	for(i=0;i<arcnum;i++){
		char arc[2];
		int weight;
		int vex1,vex2;
		while(scanf("%s%d",arc,&weight)!=2||strlen(arc)!=2||arc[0]==arc[1]){
			printf("输入第%d条边时有误,请重新输入该边",i+1);
		}
		vex1=strchr(vex,arc[0])-vex;
		vex2=strchr(vex,arc[1])-vex;//求边的两点在点集中的下标
		G.arcs[vex1][vex2]=weight;
	}
}
void PrintUDN(MGraph G){
	int i,j;
	printf("\t");
	for(i=0;i<G.vexnum;i++){
		printf("%c\t",G.vexs[i]);
	}
	printf("\n");
	for(i=0;i<G.vexnum;i++){
		printf("%c\t",G.vexs[i]);
		for(j=0;j<G.vexnum;j++){
			if(G.arcs[i][j]==INFINITY)
				printf("∞\t");
			else 
				printf("%d\t",G.arcs[i][j]);
		}
		printf("\n");
	}
}
void  MiniPath (MGraph G, ShortMatrix minedge,char vo)
{
	int  i, j, k, z,s;
	z=strchr(G.vexs,vo)-G.vexs;
	for(i=0;i<strlen(G.vexs);i++){
		minedge[i].lowcost=G.arcs[z][i];
		minedge[i].pre=0;
	}//初始化minedge数组,将其值设定为v0与各点直接相连的距离
	for(i=0;i<strlen(G.vexs);i++){
		for(j=0;j<strlen(G.vexs);j++){
			if(G.arcs[i][j]+minedge[i].lowcost<minedge[j].lowcost){/*相当于D[i]=(D[j]+{j,i}<D[i])?D[j]+{j,i}:D[i]*/
				minedge[j].lowcost=G.arcs[i][j]+minedge[i].lowcost;
				minedge[j].pre=i;
				for(s=0;s<strlen(G.vexs);s++){
					if(minedge[j].lowcost+G.arcs[j][s]<minedge[s].lowcost){
						minedge[s].pre=j;
						minedge[s].lowcost=minedge[j].lowcost+G.arcs[j][s];
					}
				}//由于minedge[i]的改变可能会影响v0到其他点的最小距离,这个循环用来更新minedge数组
			}
		}
	}
}

void  PrintPath(MGraph G, ShortMatrix minedge,char vo)
{
	int i,j,k;
	for(i=1;i<strlen(G.vexs);i++){
		char vex[MAX_VERTEX_NUM];
		j=i;
		k=0;
		while(1){
			vex[k]=G.vexs[j];
			if(minedge[j].pre==0){
				break;
			}
			j=minedge[j].pre;
			k++;
		}
        printf("%c",vo);
		for(j=k;j>=0;j--){
			printf("-->%c",vex[j]);
		}
		if(minedge[i].lowcost<INFINITY){
			printf("  长度%d\n",minedge[i].lowcost);
		}
		else{
			printf("  无路径\n");
		}
	}
}

运行结果


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值