例题:
节点个数:8
节点名称:重庆 北京 成都 上海 深圳 杭州 广州 武汉
1 2 24
1 3 47
1 4 70
2 3 25
2 5 120
3 4 23
3 5 88
3 6 66
4 6 31
4 7 42
5 6 31
5 8 29
6 7 74
6 8 79
7 8 66
打印显示要求:
1、要求打印所有节点信息:
例如:节点1:重庆;
节点2:**;
**********;
2、 要求打印所有边的信息:
例如:节点* 节点* 路径长度*
3、最短路径信息:
源节点*到节点*的最短路径长度*;
必经节点**。。。。。。;
#include <stdlib.h>
#include <stdio.h>
#define SIZE 10
#define INF 10000
struct point
{
char name[20];
int vexnum1;
int vexnum2;
int quan;
} PON[200];
/*相关函数的声明*/
void readfile(); // 读取文件函数
void writefile(); // 写入文件函数
int dijkstra(int from, int to);//迪杰斯特拉算法
/*全局变量的定义*/
int map[SIZE][SIZE];//储存地图数据
int pre[SIZE][SIZE];//储存求最短路径中间节点的数据
int len[SIZE];//储存最短路径长度
int visit[SIZE];//标记已经访问过的节点
int m, n;
int k;
FILE *fp;
int main()
{
readfile();
int i, j;
n = 8;
m = 15;
for (i = 0; i <= n; i++)
{
for (j = 0; j <= n; j++)
{
map[i][j] = INF;
}
}
int d;
printf("按序号输入节点名称: \n");
for (k = 1; k <= 8; k++) // 导入节点信息
{
printf("%d.", k);
scanf("%s", &PON[k].name);
}
for (k = 1; k <= 15; k++) // 导入节点信息
{
printf("\n\t\t-------输入节点信息-------\n");
printf("节点序号: ");
scanf("%d", &PON[k].vexnum1);
m = PON[k].vexnum1;
printf("相邻节点序号:");
scanf("%d", &PON[k].vexnum2);
n = PON[k].vexnum2;
printf("权重:");
scanf("%d", &PON[k].quan);
d = PON[k].quan;
printf("\n");
map[m][n] = d;
map[n][m] = d; // 无向图,将矩阵对称
}
/*map[1][2] = 24; // 测试数据:可以直接打印进去,也可以用文件有关的函数手动输入进去
map[1][3] = 47;
map[1][4] = 70;
map[2][3] = 25;
map[2][5] = 120;
map[3][4] = 23;
map[3][5] = 88;
map[3][6] = 66;
map[4][6] = 31;
map[4][7] = 42;
map[5][6] = 31;
map[5][8] = 29;
map[6][7] = 74;
map[6][8] = 79;
map[7][8] = 66;
int temp = INF;
for (i = 1; i <= n; ++i)
{
for (j = 1; j <= n; ++j)
{
if (map[i][j] == temp)
map[i][j] = map[j][i];
}
}
printf("显示生成的矩阵:\n");
for (i = 1; i <= n; i++)
{
printf("|");
for (j = 1; j <= n; j++)
{
if (map[i][j] == 10000)
{
printf("∞ ");
}
else
{
if (map[i][j] < 100)
printf("%d ", map[i][j]);
else
printf("%d ", map[i][j]);
}
}
printf("|\n");
}*/
writefile();
int a, b, min, len;
for (a = 1; a <= 8; a++)
{
for (b = a + 1; b <= 8; b++)
{
len = dijkstra(a, b);
printf("起点%s的到终点%s的中间过程:\n", PON[a].name, PON[b].name);
printf("起点的编号 下一站点编号 起点到该点的距离\n");
for (i = a; i <= b && pre[b][i] != -1; i++)
{
min = dijkstra(a, pre[b][i]);
printf(" %d %d %d\n", i, pre[b][i], min);
}
printf("起点%d%s的到终点%d%s的最短距离为:%d\n", a, PON[a].name, b, PON[b].name, len);
printf("必经的节点有:");
j = 1;
int q;
while (pre[b][j] != -1)
{
q = pre[b][j];
printf("\t%s", PON[q].name);
j++;
}
printf("\n");
printf("--------------------------------------------------------");
printf("\n\n");
}
}
getchar();//此行可省略
return 0;
}
void readfile()
{
int i;
if ((fp = fopen("map.txt", "r")) == NULL)
{
printf("\n\t\t 文件不存在");
if ((fp = fopen("txl.txt", "w")) == NULL)
{
printf("\n\t\t 建立失败");
exit(0);
}
else
{
printf("\n\t\t-------文件已建立-------");
getchar();
return;
}
exit(0);
}
fseek(fp, 0, 2);
if (ftell(fp) > 0)
{
rewind(fp);
for (i = 0; !feof(fp) && fread(&PON[i], sizeof(struct point), 1, fp); i++)
;
printf("\n\t\t 文件导入成功");
printf("\n\t\t-------------------");
getchar();
return;
}
printf("\n\t\t文件导入成功");
printf("\n\t\t文件中无任何信息");
getchar();
return;
}
void writefile()
{
int i;
if ((fp = fopen("map.txt", "w")) == NULL)
{
printf("\n\t\t文件打开失败");
}
for (i = 0; i < 200; i++)
{
if (fwrite(&PON[i], sizeof(struct point), 1, fp) != 1)
{
printf("\n\t\t 写入文件错误");
}
}
fclose(fp);
printf("\n\t\t写入文件完毕");
printf("\n\t--------------------------\n");
}
int dijkstra(int from, int to)
{ // 从源点到目标点
int i, j, k;
for (i = 1; i <= n; i++)
{ // 初始化
visit[i] = 0; // 一开始每个点都没被访问
len[i] = map[from][i]; // 先假设源点到其他点的距离
for (j = 1; j <= n; j++)
pre[i][j] = -1;
if (INF > len[i])
{
pre[i][0] = from;
pre[i][1] = i;
}
}
for (i = 1; i < n; ++i)
{ // 对除源点的每一个点进行最短计算
int min = INF; // 记录最小len[i]
int pos; // 记录小len[i] 的点
for (j = 1; j <= n; ++j)
{
if (!visit[j] && min > len[j])
{
pos = j;
min = len[j];
}
}
visit[pos] = 1;
for (j = 1; j <= n; ++j)
{
if (!visit[j] && (len[j] > (len[pos] + map[pos][j])))
{
len[j] = len[pos] + map[pos][j]; // 更新j节点到源节点的最短路径
for (k = 1; k <= n; k++)
{
pre[j][k] = pre[pos][k];
if (pre[j][k] == -1)
{
pre[j][k] = j;
break;
}
}
}
}
}
printf("\n");
return len[to];
}
运行结果如下:
我也不知道迪杰斯特拉算法部分的原作者是谁,但是那个算法只有最短路径的结果,没有中间节点的打印,我自己修修改改了一点,欢迎大家指正。