单源最短路径---贪心法实现(Dijkstra算法)

8 篇文章 0 订阅
4 篇文章 0 订阅



结果





数据为项目目录下的 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;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值