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;
}