数据结构——Dijkstra算法求解最短路径

这个实验在学长的帮助下终于搞懂了,感谢学长!!!!!!激动!!!

数据结构——Dijkstra算法求解最短路径_第1张图片

数据结构——Dijkstra算法求解最短路径_第2张图片

#include 
#include 
using namespace std;

int vex_num;		// 表示站点个数

int start_point;	// 表示出发站点的序号

char *station;		// 指向站点名(大写字母)字符数组的指针

int **adjmat;		// 指向表示邻接矩阵的二维数组的指针

int *prev;			// 指向表示最短路径上前驱站点位置数组的指针

int *dist;			// 指向最短距离数组的指针

/** 求解最短路径的Dijkstra算法.
 *  u - 出发站点的索引ID;
 */
void path_Dijkstra(int u) {
	int i, j; //i,j-循环变量

+
	//数组set[n],标识一个顶点是否已加入S中(1-已加入;0-还未加入),S为已求得最短路径的终点集
	int *set = new int[vex_num];
 
	//************************************************
	/* (1)初始化数组dist[], prev[], set[] */
	for(i=0; i<vex_num; i++) {
		//(1.1)从起始点u出发->到站点i的: [当前]最短路径
		dist[i] = adjmat[u][i];

		//(1.2)从起始点u出发->到站点i的最短路径,点i前一个顶点是(u? -1表示无路径)
		if(dist[i] != 9999) {
			prev[i] = u;
		} else {
			prev[i] = -1;
		}

		//(1.3)标识顶点i否已加入S中(S为已求得最短路径的终点集)
		set[i] = 0;
	}

	/* (2)将出发站点u加入S中,即u为已求得最短路径的终点! */
	//dist[u] = 0;
	set[u] = 1;

	/* (3)除出发站点u之外的其余n-1个顶点, 寻找最短路径(循环n-1次) */
	for(i=0; i<vex_num; i++) {
		//(3.1)本次循环(i),dist[]中的最短距离值,及其对应的顶点序号
		int min = 9999; // 最短距离值
		int v = -1; //具有最短距离值的顶点序号
		for(j=0; j<vex_num; j++) {
			if(set[j]==0 && dist[j]<min ) {//若站点[j]不在S中,且距离比当前最小距离值更小
				min = dist[j]; //更新:最小距离值
				v = j; //更新:最小距离值对应的顶点序号
			}
		}

		//(3.1-后处理)若找到的最小距离值 为9999,距离无穷大(即没有弧),则退出此次循环&进入下一次
		if(min == 9999) {
			continue;
		}

		//(3.2)将站点v加入S中,即v为已求得最短路径的终点!
		set[v] = 1;

*		//(3.3)v点加入后, 修改受之影响的站点的dist[] 和 pre[]的值
		for(j=0; j<vex_num; j++) {
			//若站点j不在S中,且u经v到j的距离<之前u到j的距离,则更新u到j的最短距离 及j的前序站点...
			if( set[j]==0 && (dist[v] + adjmat[v][j] < dist[j]) ) {
				dist[j] = dist[v] + adjmat[v][j]; //更新[点u]到[点j]的最短距离
				prev[j] = v; //最短路径中,点j的前一个顶点是v
			}
		}
	}
	//================================================
}

/** 输出某一终点的最短路径和最短距离.
 * v - 指定的目标站点索引ID;
 * 思想: Dijkstra算法计算出各最短路径上每个终点的前驱站点以及各最短路径的长度, 利用栈(通过回溯的方法)输出最短路径.
 */
void output_path(int v) {
	//(1)初始化栈路径栈(逆向)
	int *stack = new int[vex_num];
	int top = -1; //栈顶指针=-1,表示栈为空

	//(2.1)初始时刻,获取站点v的前驱站点u,... 
	int u = prev[v]; //站点v的前驱站点-->站点u 
	while( u!=-1 && u!=start_point-1) { //若前驱站点存在(!=-1)且不是出发站点(!=start_point-1),则... 
		stack[++top] = u; //前驱站点u 进栈
		
		u = prev[u]; //下一个前驱站点 
	}
	
	//(2.2)最后时刻, 将出发站点(start_point-1) 进栈 
	stack[++top] = start_point-1;
	
	//(3.1)首先, 进行栈中元素的输出(逐一出栈) 
	while(top != -1) { //若栈非空(!=-1),... 
		u = stack[top--]; //栈顶元素出栈,且栈顶指针下移!
		 
		cout << station[u] <<"->"; //输出栈顶元素对应的[站点名称] 
	}
	
	//(3.2)最后,目标站点名称 及其最短路径长度 
	cout << station[v]<<":"<<dist[v]<<endl;
}

int main() {
	int i, j; //i,j-循环变量 
	FILE *fp;
	if((fp=fopen("exp04.in", "r")) != NULL ) {
		fclose(fp);  //存在的话,要先把之前打开的文件关掉

		freopen("exp04.in", "r", stdin);
		freopen("exp04.out", "w", stdout);
	}

	cin >> vex_num; //站点数目
	cin >> start_point; //出发站点的序号(从1开始,第一个站点为A)

	//(1)建立和初始化站名数组
	station = new char[vex_num];
	for(i=0; i<vex_num; i++) {
		station[i] = 'A'+i; //站点依次为A,B,C,D
	}

	//(2)建立表示邻接矩阵的二维数组 & 初始化
	adjmat = new int* [vex_num];
	for(i=0; i<vex_num; i++) {
		adjmat[i] = new int[vex_num]; //为二维数组第i行分配空间

		for(j=0; j<vex_num; j++) {
			cin >> adjmat[i][j]; //为二维数组第i行元素赋值
		}
	}

	//(3.1)建立表示最短路径上前驱站点位置的数组
	prev = new int[vex_num];

	//(3.2)建立表示最短距离的数组
	dist = new int[vex_num];

	//(4)求解最短路径和距离
	path_Dijkstra(start_point-1);

	//(5)输出最短路径和距离
	for(i=0; i<vex_num; i++) {
		if(i != start_point-1) {
			output_path(i); //利用栈(通过回溯的方法)输出最短路径
		}
	}

	return 0;
}

你可能感兴趣的:(数据结构)