迪科斯特算法

C++代码实现:曾记否,去年搞了至少一个多月C++,现在看来,什么都没有学到.而算法从一个侧面来说可以达到学以致用的目的.既在找到了道路就要坚持下去,毕竟自己的年龄已经不允许自己再反复了.

/*Dijkstra算法,解决单源最短路径算法*/

#include "stdafx.h"
#include <iostream>
#include <cstdio>/*cstdio是将stdio.h的内容用C++头文件的形式
表示出来。stdio.h是C标准函数库中的头文件*/
#include <cstring>/*<string>是C++标准库头文件,包含了拟容器
class std::string的声明(不过class string事实上只是
basic_string<char>的typedef),用于字符串操作。
<cstring>是C标准库头文件<string.h>的C++标准库版本,
包含了C风格字符串(NUL即'\0'结尾字符串)相关的一些类型和函
数的声明,例如strcmp、strchr、strstr等。<cstring>和<string.h>的
最大区别在于,其中声明的名称都是位于std命名空间中的,而不是后者
的全局命名空间。*/
#include <windows.h>
#include <stack>/* stack堆栈容器的C++标准头文件为 stack*/

using namespace std;
const int N = 100;//城市的个数
const int INF = 1e7;//无究大10000000
int map[N][N], dist[N], p[N], m, n;//n为城市的个数,m为城市间线路的条数
bool flag[N];//等于true, 说明已经加入到顶点集全S中,否则还在路径集合v-s中

void Dijkstra(int u){
	for (int i = 1; i <= n; i++){
		dist[i] = map[u][i];
		flag[i] = false;
		if (dist[i] == INF)p[i] = -1;
		else p[i] = u;//记录前驱
	}
	dist[u] = 0;
	flag[u] = true;//初始化时集合只有一个结点u
	//在v-s中找最小的结点
	for (int i = 1; i <= n; i++){
		int temp = INF;
		int t = u;
		for (int j = 1; j <= n; j++){
			if (!flag[j] && dist[j] < temp){
				t = j;//记录离源点最近的点
				temp = dist[j];
			}
		}
		if (t == u)return;//找不到t退出
		flag[t] = true; //将t加到到集合s 中
		//更新V-s中与t邻接的顶点到源点 u 的距离
		for (int j = 1; j <= n; j++){
			if (!flag[j] && map[t][j] < INF){//!flag[j]表明是j在v-s集合中
				if (dist[j]>(dist[t] + map[t][j])){
					dist[j] = dist[t] + map[t][j];
					p[j] = t;
				}
			}
		}
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	int u, v, w, st;
	system("color 0d");
	cout << "请输入城市的个数: " << endl;
	cin >> n;
	cout << "请输入城市间路径的条数: " << endl;
	cin >> m;
	cout << "请输入城市间路线及其距离: " << endl;
	for (int i = 1; i <= n;i++)
	for (int j = 1; j <= n; j++){
		map[i][j] = INF;//初始化邻接矩阵为无穷大
	}
	while (m--){
		cin >> u >> v >> w;
		map[u][v] = min(map[u][v], w);//邻接矩阵储存,保留最小的距离
	}
	cout << "请输入位置" << endl;
	cin >> st;
	Dijkstra(st);
	cout << "所在的位置为 " << st << endl;
	for (int i = 1; i <= n; i++){
		cout << "所在位置 " << st << "  -  " << "要去的位置" <<i<< endl;
		if (dist[i] == INF)cout << "无路可去" << endl;
		else cout << "最短距离为 " <<dist[i] << endl;
	}
	return 0;
}


C代码实现:其实不算很难,但开始的时候,还是不太明白迪科斯特所要解决的问题.其实就是解决从已知源点到其他点的最短路径问题.另外,在flag[]中是很关键的一个标志,因为加入到最短顶点集合后,就从剩下的顶点找最短的,然后从这个最短的点开始再找其他剩下点的路径长度。

/*Dijkstra算法,解决单源最短路径算法*/

#include "stdafx.h"
#include <stdio.h>

#pragma warning(disable:4996)

#define N 100
#define INF 10000000

int n, m;//n为顶点的个数m为顶点间路径的条数
int dist[N];//存储的是顶点间最短的距离,相对于指定的某个顶点来说
int p[N];//存储的是前驱结点
int map[N][N];//抽象出来的数据结构,存储任意两顶点间的距离
int flag[N];//是否加入到最短距离顶点集合
void Dijkstra(int u){//迪科斯彻算法,输一个起始点,到各点的最距离
	for (int i = 1; i <= n; i++){//初始化起始结点到各结点的距离
		dist[i] = map[u][i];
		flag[i] = false;
		if (dist[i] == INF)p[i] = -1;
		else p[i] = u;
	}
	dist[u] = 0;//起初只有一个源点的时候
	flag[u] = true;
	for (int i = 1; i <= n; i++){//寻找从源点出发直接连接的最短路径的顶点
		int min = INF; int t = u;
		for (int j = 1; j <= n; j++)
		if (!flag[j] && dist[j] < min){
			min = dist[j];
			t = j;
		}
		if (t == u)return;
		flag[t] = true;//将最近路径点加入集合
		for (int i = 1; i <= n; i++){//从新加入的点出发寻找到其他结点的最短路径
			if (!flag[i] && map[t][i] < INF){
				if (dist[i]>(dist[t] + map[t][i]))
				{
					dist[i] = dist[t] + map[t][i];
					p[i] = t;
				}
			}
		}
	}

}

int _tmain(int argc, _TCHAR* argv[])
{
	int v, k, w;
	int st;
	printf("输入顶点的个数n: ");
	scanf("%d", &n);
	printf("输入顶点间路径的条数m: ");
	scanf("%d", &m);
	//初始化顶点间路径权值为无穷大
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= n; j++){
		if (i == j)map[i][j] = 0;
		else map[i][j] = INF;
	}
	printf("输入顶点1编号v,顶点2编号k及两顶点间的权值w\n");
	for (int i = 1; i <= m; i++){
		scanf("%d%d%d", &v, &k, &w);
		map[v][k] = w;
	}
	printf("请输入源点的编号st");
	scanf("%d", &st);
	//
	Dijkstra(st);
	//
	printf("所在的位置编号st=%d", st);
	for (int j = 1; j <= n; j++){
		printf("所在的位置  %d----要去的位置   %d", st, j);
		if (dist[j] == INF)printf("无路可去\n");
		else printf("最短距离为%d\n", dist[j]);
	}

	return 0;
}


猜你喜欢

转载自blog.csdn.net/guangod/article/details/81904981