迪杰斯特拉算法C语言

例题:


节点个数: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];
}

运行结果如下:
 

        我也不知道迪杰斯特拉算法部分的原作者是谁,但是那个算法只有最短路径的结果,没有中间节点的打印,我自己修修改改了一点,欢迎大家指正。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值