1. 程式人生 > >Dijkstra演算法求最短路徑問題完整C程式碼

Dijkstra演算法求最短路徑問題完整C程式碼

<pre name="code" class="cpp">/* Dijkstra演算法求圖的最短路徑問題C程式碼 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MaxSize 20
#define INFINITY 65535

typedef char VertexType;

 //定義圖 的鄰接矩陣表示法結構
typedef struct Graph {
	VertexType ver[MaxSize+1];
	int edg[MaxSize][MaxSize];
}Graph;

//鄰接矩陣法圖的生成函式
void CreateGraph( Graph *g )
{
	int i = 0;
	int j = 0;
	int VertexNum;
	VertexType Ver;

	printf("請輸入圖的頂點:\n");
	while( '\n' != (Ver=getchar()) )
		g->ver[i++] = Ver;
	g->ver[i] = '\0';

	VertexNum = strlen(g->ver);
	printf("請輸入相應的的鄰接矩陣:\n");
	for( i=0; i<VertexNum; i++ )
		for( j=0; j<VertexNum; j++ )
			scanf("%d", &g->edg[i][j]);
}

//列印圖的結點識別符號和鄰接矩陣
void PrintGraph( Graph g )
{
	int i, j;
	int VertexNum = strlen(g.ver);
	printf("圖的頂點為:\n");
	for( i=0; i<VertexNum; i++ )
		printf("%c ", g.ver[i]);
	printf("\n");

	printf("圖的鄰接矩陣為:\n");
	for( i=0; i<VertexNum; i++ ) {
		for( j=0; j<VertexNum; j++ )
			printf("%d ", g.edg[i][j]);
		printf("\n");
	}
}

//求圖的頂點數
int CalVerNum( Graph g )
{
	return strlen(g.ver);
}

//將不鄰接的頂點之間的權值設定為INFINITY
void SetWeight( Graph *g )
{
	for( int i=0; i<CalVerNum(*g); i++ )
		for( int j=0; j<CalVerNum(*g); j++ )
			if( 0 == g->edg[i][j] )
				g->edg[i][j] = INFINITY;
}

//Dijkstra求最短路徑函式
void Dijkstra( Graph g )
{
	int VertexNum = CalVerNum( g );
	int j;
	int mini;
	int index = 0;
	int *used = (int *)malloc(sizeof(int)*VertexNum);
	int *distance = (int *)malloc(sizeof(int)*VertexNum);
	int *parent = (int *)malloc(sizeof(int)*VertexNum);
	int *last = (int *)malloc(sizeof(int)*VertexNum);

	SetWeight( &g );					//設定權值

	for( int i=0; i<VertexNum; i++ ) {
		used[i] = 0;
		distance[i] = g.edg[0][i];   //初始化為與編號為0的頂點的距離
		last[i] = 0;
	}

	used[0] = 1;
	parent[index++] = 0;

	for( i=0; i<VertexNum-1; i++ ) {
		j = 0;
		mini = INFINITY;

		for( int k=0; k<VertexNum; k++ )
			if( (0 == used[k]) && (distance[k] < mini) ) {
				mini = distance[k];
				j = k;			//j為剛剛找到的V-U中到源點路徑最短的頂點
			}
		
		used[j] = 1;

		for( k=0; k<VertexNum; k++ ) 
			if( (0 == used[k]) && (distance[k] > distance[j] + g.edg[j][k]) ) {   //由於有頂點新加入U集合,對距離陣列distance進行更新,比較原路徑長度與以新加入的頂點為中間點的路徑長度
				distance[k] = distance[j] + g.edg[j][k];
			}

		parent[index++] = j;
	}

	printf("%c到%c的最短路徑經過頂點依次為:\n", g.ver[0], g.ver[VertexNum-1]);
	for( i=0; i<index; i++ )
		printf("%c ", g.ver[parent[i]]);
	printf("\n");

	printf("最短路徑長度為: %d\n", mini);
	
}

int main()
{
	Graph g;
	CreateGraph( &g );
	PrintGraph( g );

	Dijkstra( g );
	return 0;
}

測試資料及結果