單源最短路徑---貪心法實現(Dijkstra算法)



結果





數據爲項目目錄下的 mat.txt 文件。

5
0    10    999    30    100
999    0    50    999    999
999    999    0    999    10
999    999    20    0    60
999    999    999    999    0


/********************************************************************
 *    FILER.H    文件註釋
 *    文件路徑:    D:\EVERBOX\SOURCE CODE\貪心法\單源最短路徑/
 *    作者    :    mpl2
 *    創建時間:    2011/12/3 20:34
 *    文件描述:    
 *********************************************************************/
#ifndef _FILER_H_
#define _FILER_H_

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

/*
*	打開文件,轉換爲數組。格式:第一行爲數組大小,從第二行開始爲數據,以
*  製表符\t爲分隔符。
*/
int fileRead(const char* filePath,int** &returnArray);

#endif

/********************************************************************
 *    FILER.CPP    文件註釋
 *    文件路徑:    D:\EVERBOX\SOURCE CODE\貪心法\單源最短路徑/
 *    作者    :    mpl2
 *    創建時間:    2011/12/3 20:34
 *    文件描述:    
 *********************************************************************/

#include "fileR.h"

int fileRead(const char* filePath,int** &returnArray){
	if( !filePath ){
		returnArray = NULL;
		return 0;
	}

	FILE* fp = fopen(filePath, "r");
	if( fp == NULL){
		printf("ERROR:File not exist\n");
		exit(-1);
	}

	int arrayNum = 0;
	//fread(&arrayNum, sizeof(int), 3, fp);
	fscanf(fp, "%d\n", &arrayNum);
	returnArray = (int**)malloc( (arrayNum+1)*sizeof(int*) );
	if( arrayNum > 0 ){
		for (int i = 0; i < arrayNum+1 ; i++ ) {
			returnArray[i] = (int*)malloc( (arrayNum+1)*sizeof(int) );
		}

		for (int j = 1; j < arrayNum+1 ; j++ ) {
			for (int x = 1; x < arrayNum+1 ; x++ ) {
				if ( x == arrayNum ) {/* 假如讀到每行最後一個數字 */
					fscanf(fp, "%d\n", &(returnArray[j][x] ));
				}else
					fscanf(fp, "%d\t", &(returnArray[j][x] ));
			}
		}
	}
	fclose(fp);

	return arrayNum;
}



/********************************************************************
 *    MAIN2.CPP    文件註釋
 *    文件路徑:    D:\EVERBOX\SOURCE CODE\貪心法\單源最短路徑/
 *    作者    :    mpl2
 *    創建時間:    2011/12/3 20:33
 *    文件描述:    
 *********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "fileR.h"

#define MAX_INT 999

/*
* n表示節點數,v表示源節點;
* dist[i:n];表示第i個點到第n個點的最短特殊路徑長度;
* c[i][j]表示邊(i,j)的權;
*/
void Dijkstra(int n,int v,int* dist,int* prev,int** c){
	// 下標從1開始,s數組表示是否在S集合中.範圍是 1 到 n
	bool* s = (bool*)malloc( (n+1) * sizeof(bool) );	
	for(int i=1; i <= n; i++){
		//初始化時,只有v在集合S中,其餘節點都不在
		dist[i] = c[v][i];
		s[i] = false;
		// 假如源節點沒有直接到第i個節點
		if( dist[i] == MAX_INT ){
			prev[i] = 0;
		}else{
			prev[i] = v;
		}
	}
	dist[0] = 0;//v到v的距離是0
	s[v] = true;//初始化v就在集合s中
	// dist數組 [2:n]需要完成
	for(int i=1; i <= n-1; i++){
		int tem = MAX_INT;
		int u = v;//表示當前在集合S中的點
		// 從不在集合s中的點,選取一個距源點v最短的一個點
		for(int j=1; j <= n; j++){
			if( !s[j] && dist[j]<tem){
				tem = dist[j];
				u = j;
			}
		}
		s[u] = true; // 將選出的距離最短的點放入集合S
		//將u放入集合S後,更新dist數組
		// if dist[u] + c[u][j] < dist[j] 需要更新 dist[j] , prev[j]
		for(int j=1; j <= n; j++){
			if ( dist[j] > dist[u] + c[u][j] ) {
				dist[j] = dist[u] + c[u][j];
				prev[j] = u;
			}
		}
	}
	free(s);

}
/*
for (int i = num; i >= 2 ; i-- ) {
printf("點%d 到 點%d 的最短路徑長度: %d\n", v, i, dist[i]);

int p = prev[i];
while ( p != 0 ) {
printf(" %d ",p);
p = prev[p];
}
printf("\n",p);
}*/

void showPath( int* prev,int p, int endP){
	if ( p != endP ) {
		showPath( prev, prev[p], endP);
		printf("%d ",prev[p]);
	}
}

int main(){
	int** c = 0;
	int v = 1;
	int num = fileRead("mat.txt", c);
	int* dist = (int*)malloc((num+1)*sizeof(int));
	int* prev = (int*)malloc((num+1)*sizeof(int));
	prev[0] = 0;
	prev[1] = 0;

	dist[0] = 0;
	dist[1] = 0;
	/*

	for (int i = 1; i < num+1 ; i++ ) {
	for (int j = 1; j < num+1 ; j++ ) {
	if ( j == num ) {
	printf("%d\n",c[i][j]);
	}else
	printf("%d\t",c[i][j]);
	}
	}*/

	printf("input the source node v :");
	scanf("%d",&v);
	printf("\n\n" );
	Dijkstra(num, v, dist, prev, c);
	
	/*
	for ( int i = 0; i < num+1; i++ ) {
		printf("%d ",prev[i]);
		}
		printf("\n " );
		for ( int i = 0; i < num+1; i++ ) {
		printf("%d  ",dist[i]);
		}*/
	
	for (int i = num; i >= 2 ; i-- ) {
		if ( dist[i] != MAX_INT && dist[i] > 0) {
			printf("point %d to point %d, lenth is: %d\n", v, i, dist[i]);
			printf("the path is :" );
			showPath(  prev, i , v);
			printf("\n\n" );
		}
		
	} 

	return 0;

}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章