一、数据结构
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
二、核心算法—Dijkstra算法
/*初始化路径矩阵*/
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];
}
}
}
}
三、完整代码
#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;
}
输出结果:
从v1到v6:
从v4到v6: