数据结构 | 图的最短路径 Dijkstra算法

一、数据结构定义

typedef int VexType;
typedef int AdjType;

/*图*/ 
typedef struct{
    VexType vexs[VN];		//结点 
    AdjType arcs[VN][VN];	//权值 
}GraphMatrix; 

/*路径*/ 
typedef struct{
    AdjType length;			 
    VexType prevex;			
}Path;				
Path dist[VN];

1.二维数组 arcs[VN][VN] 储存图的边权数据,一维数组 vexs[VN] 储存图的结点数据;

2.结构体 Path 保存起始点到每个结点的最短距离length,到该点的最短距离的上一个结点prevex

二、算法详解

/*初始化路径矩阵*/
void Init_Path(GraphMatrix *G, Path dist[]){
	dist[0].length = 0;
	dist[0].prevex = 0;
	G->arcs[0][0] = 1;
	for(int i=1; i<VN; ++i){
		dist[i].length = G->arcs[0][i];
		if(dist[i].length != MAX)	dist[i].prevex = 0;
		else 						dist[i].prevex = -1;
	}
}

/*Dijkstra算法寻找最短路径*/
void Dijkstra(GraphMatrix *G ,Path dist[]){
	int i,j,min_vex,min_length;
	
	Init_Path(G,dist);
	
	for(i=1; i<VN; ++i){
		min_length = MAX;	//当前到Vi的最短路径长度 
		min_vex = 0;		//当前到Vi的最短路径对应的上一个结点
		 
		for(j=1; j<VN; ++j){
			if(G->arcs[j][j] == 0 && dist[j].length < min_length){
				min_vex = j;
				min_length = dist[j].length;
			}
		}
		if(min_vex == 0) break;
		G->arcs[min_vex][min_vex] = 1;
		
		for(j=1; j<VN; ++j){
			if(G->arcs[j][j] == 0 && dist[j].length > dist[min_vex].length + G->arcs[min_vex][j]){
				dist[j].prevex = min_vex;
				dist[j].length = dist[min_vex].length + G->arcs[min_vex][j];
			}
		}
	}
}

三、运行结果

        main方法代码如下:

int main(){
	int i,j;
	GraphMatrix *G =Init_Graph();
	
	Print_Graph(G);
	Dijkstra(G,dist);
	Print_Path(dist);
	
	printf("起点:"); scanf("%d",&i);
	printf("终点:"); scanf("%d",&j);
	if(Find(i,G) != -1 && Find(j,G) != -1) 
		Print_Length(Find(i,G),Find(j,G),dist,G);
    return 0;
}

 

        输出:

        从v1到v6:

        从v4到v6: 

四、源代码

#include <stdio.h>
#include <stdlib.h>
#define VN 	6				//邻接矩阵大小(v0 - v5) 
#define MAX 999				//不可到达点的权值(即无穷大)

typedef int VexType;
typedef int AdjType;

/*图*/ 
typedef struct{
    VexType vexs[VN];		//结点 
    AdjType arcs[VN][VN];	//权值 
}GraphMatrix; 

/*路径*/ 
typedef struct{
    AdjType length;			 
    VexType prevex;			 
}Path;				
Path dist[VN];


/*打印图的邻接矩阵*/
void Print_Graph(GraphMatrix *G){
	int i,j;
	printf("G->arcs[][] = \n\t");
	for(i=0; i<VN; ++i) 
		printf(" V%d \t",G->vexs[i]);
		printf("\n");
	
	for(i=0; i<VN; ++i){
		printf(" V%d \t",G->vexs[i]);
  		for(j=0; j<VN; j++)
			printf(" %d \t",G->arcs[i][j]);
		printf("\n");
 	}
 	printf("\n");
}

/*打印图的路径矩阵*/
void Print_Path(Path dist[]){
	printf("dist[] = \n");
	for(int i=0; i<VN; i++)
		printf(" V%d: prevex = %d   lenght = %d\n",i,i,dist[i].length,i,dist[i].prevex);
	printf("\n"); 
}

/*打印两点间的最短路径*/
void Print_Length(int start_vex, int end_vex, Path dist[], GraphMatrix *G){
	if(start_vex > end_vex || end_vex > VN-1 || start_vex < 0) {
		printf("输入错误!");
		return;
	}
	int i = end_vex;
	printf("%d -> ",G->vexs[end_vex]);
	while(dist[i].prevex != start_vex){
		printf("%d -> ",G->vexs[dist[i].prevex]);
		i = dist[i].prevex;
	}
	printf("%d = %d",G->vexs[start_vex],dist[end_vex].length - dist[start_vex].length);
	return;
}

/*寻找结点G->vexs[i]对应的储存位置i*/
int Find(int find_point, GraphMatrix *G){
	for(int i=0; i<VN; i++)
		if(G->vexs[i] == find_point) return i;
	return -1;
}

/*初始化图并输入权值*/
GraphMatrix* Init_Graph(){
	int begin,end,weight,i,j;
    GraphMatrix *G = (GraphMatrix*)malloc(sizeof(GraphMatrix));
    
	/*初始化图的邻接矩阵 arcs[VN][VN] */
	for (i=0; i<VN; i++){ 
		for (j=0; j<VN; j++){
			if(i == j)	G->arcs[i][j] = 0;		//对角线权值为0 
			else		G->arcs[i][j] = MAX;	//除对角线外所有权值为无穷大 
		}
	} 
	
	/*初始化图的结点矩阵 vexs[VN] */ 
	int v[VN] = {1,2,3,4,5,6};
	for(i=0; i<VN; i++)
		G->vexs[i] = v[i];
		
	/*初始化图的边权*/
	int  start_vex[9] = {0,0,1,1,3,3,2,3,4};
	int    end_vex[9] = {1,2,2,3,2,4,4,5,5};
	int vex_weight[9] = {1,12,9,3,4,13,5,15,4};
	for(i=0; i<9; i++)
		G->arcs[start_vex[i]][end_vex[i]] = vex_weight[i];
	return G;
}

/*初始化路径矩阵*/
void Init_Path(GraphMatrix *G, Path dist[]){
	dist[0].length = 0;
	dist[0].prevex = 0;
	G->arcs[0][0] = 1;
	for(int i=1; i<VN; ++i){
		dist[i].length = G->arcs[0][i];
		if(dist[i].length != MAX)	dist[i].prevex = 0;
		else 						dist[i].prevex = -1;
	}
}

/*Dijkstra算法寻找最短路径*/
void Dijkstra(GraphMatrix *G ,Path dist[]){
	int i,j,min_vex,min_length;
	
	Init_Path(G,dist);
	
	for(i=1; i<VN; ++i){
		min_length = MAX;	//当前到Vi的最短路径长度 
		min_vex = 0;		//当前到Vi的最短路径对应的上一个结点
		 
		for(j=1; j<VN; ++j){
			if(G->arcs[j][j] == 0 && dist[j].length < min_length){
				min_vex = j;
				min_length = dist[j].length;
			}
		}
		if(min_vex == 0) break;
		G->arcs[min_vex][min_vex] = 1;
		
		for(j=1; j<VN; ++j){
			if(G->arcs[j][j] == 0 && dist[j].length > dist[min_vex].length + G->arcs[min_vex][j]){
				dist[j].prevex = min_vex;
				dist[j].length = dist[min_vex].length + G->arcs[min_vex][j];
			}
		}
	}
}


int main()
{
	int i,j;
	GraphMatrix *G =Init_Graph();
	
	Print_Graph(G);
	Dijkstra(G,dist);
	Print_Path(dist);
	
	printf("起点:"); scanf("%d",&i);
	printf("终点:"); scanf("%d",&j);
	if(Find(i,G) != -1 && Find(j,G) != -1) 
		Print_Length(Find(i,G),Find(j,G),dist,G);
    return 0;
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值