C语言数据结构学习笔记(20)-有向网图的最短路径-Floyd算法及路径打印

/*
有向网图的最短路径-Floyd算法及路径打印
输出结果:
请输入图的顶点和弧的个数:
7 12
请依次输入图的7个顶点信息:
V0
V1
V2
V3
V4
V5
V6
请依次输入图的弧<Vi, Vj>上下标及对应权值:
0 1 2
0 3 1
1 3 3
1 4 10
2 0 4
2 5 5
3 2 2
3 4 2
3 5 8
3 6 4
4 6 6
6 5 1
图的邻接矩阵为:
        V0      V1      V2      V3      V4      V5      V6
V0      0       2       ∞       1       ∞       ∞       ∞
V1      ∞       0       ∞       3       10      ∞       ∞
V2      4       ∞       0       ∞       ∞       5       ∞
V3      ∞       ∞       2       0       2       8       4
V4      ∞       ∞       ∞       ∞       0       ∞       6
V5      ∞       ∞       ∞       ∞       ∞       0       ∞
V6      ∞       ∞       ∞       ∞       ∞       1       0
最终dist数组为:
        0       2       3       1       3       6       5
        9       0       5       3       5       8       7
        4       6       0       5       7       5       9
        6       8       2       0       2       5       4
        ∞       ∞       ∞       ∞       0       7       6
        ∞       ∞       ∞       ∞       ∞       0       ∞
        ∞       ∞       ∞       ∞       ∞       1       0
最终path数组为:
        0       1       3       3       3       3       3
        3       1       3       3       3       3       3
        0       0       2       0       0       5       0
        2       2       2       3       4       6       6
        0       1       2       3       4       6       6
        0       1       2       3       4       5       6
        0       1       2       3       4       5       6
各顶点间的最短路径和权值和为:
V0-V0:  V0-->V0-->(0)
V0-V1:  V0-->V1-->(2)
V0-V2:  V0-->V3-->V2-->(3)
V0-V3:  V0-->V3-->(1)
V0-V4:  V0-->V3-->V4-->(3)
V0-V5:  V0-->V3-->V6-->V5-->(6)
V0-V6:  V0-->V3-->V6-->(5)

V1-V0:  V1-->V3-->V2-->V0-->(9)
V1-V1:  V1-->V1-->(0)
V1-V2:  V1-->V3-->V2-->(5)
V1-V3:  V1-->V3-->(3)
V1-V4:  V1-->V3-->V4-->(5)
V1-V5:  V1-->V3-->V6-->V5-->(8)
V1-V6:  V1-->V3-->V6-->(7)

V2-V0:  V2-->V0-->(4)
V2-V1:  V2-->V0-->V1-->(6)
V2-V2:  V2-->V2-->(0)
V2-V3:  V2-->V0-->V3-->(5)
V2-V4:  V2-->V0-->V3-->V4-->(7)
V2-V5:  V2-->V5-->(5)
V2-V6:  V2-->V0-->V3-->V6-->(9)

V3-V0:  V3-->V2-->V0-->(6)
V3-V1:  V3-->V2-->V0-->V1-->(8)
V3-V2:  V3-->V2-->(2)
V3-V3:  V3-->V3-->(0)
V3-V4:  V3-->V4-->(2)
V3-V5:  V3-->V6-->V5-->(5)
V3-V6:  V3-->V6-->(4)

V4-V0:  V4-->V0-->(∞)
V4-V1:  V4-->V1-->(∞)
V4-V2:  V4-->V2-->(∞)
V4-V3:  V4-->V3-->(∞)
V4-V4:  V4-->V4-->(0)
V4-V5:  V4-->V6-->V5-->(7)
V4-V6:  V4-->V6-->(6)

V5-V0:  V5-->V0-->(∞)
V5-V1:  V5-->V1-->(∞)
V5-V2:  V5-->V2-->(∞)
V5-V3:  V5-->V3-->(∞)
V5-V4:  V5-->V4-->(∞)
V5-V5:  V5-->V5-->(0)
V5-V6:  V5-->V6-->(∞)

V6-V0:  V6-->V0-->(∞)
V6-V1:  V6-->V1-->(∞)
V6-V2:  V6-->V2-->(∞)
V6-V3:  V6-->V3-->(∞)
V6-V4:  V6-->V4-->(∞)
V6-V5:  V6-->V5-->(1)
V6-V6:  V6-->V6-->(0)

请按任意键继续. . .
*/
# include <stdio.h>
# include <stdlib.h>
# define VEXMAX 100
# define SIZE 5
# define INF 0X3f3f3f3f
typedef char VertexType[SIZE];
typedef int EdgeType;
typedef struct{
    VertexType vexs[VEXMAX];
    EdgeType arc[VEXMAX][VEXMAX];
    int vexNum, edgeNum;
}MGraph;
void CreateMGraph(MGraph * G);//创建图的邻接矩阵
void PrintMGraph(MGraph G);// 打印图的邻接矩阵
void Floyd(MGraph G, int ** path, int ** dist);//最短路径-弗洛伊德算法
void PrintRoad(MGraph G, int ** path, int ** dist);//打印最短路径

int main(void)
{    
    int start;
    MGraph G;
    CreateMGraph(&G);
    PrintMGraph(G);
    //创建二维数组path保存各路径下标,二维数组dist保存各顶点到各顶点的最短路径权值
    int ** path = (int **)malloc(G.vexNum * sizeof(int*));
    int ** dist = (int **)malloc(G.vexNum * sizeof(int*));
    for(int i = 0; i < G.vexNum; i++)
    {
        *(path + i) = (int*)malloc(G.vexNum * sizeof(int));
        *(dist + i) = (int*)malloc(G.vexNum * sizeof(int));
    }
    Floyd(G, path, dist);
    PrintRoad(G, path, dist);

    for(int i = 0; i < G.vexNum; i++)
    {
        free(*(path + i));
        free(*(dist + i));
        *(path + i) = NULL;
        *(dist + i) = NULL;
    }
    system("pause");
    return 0;
}
//创建图的邻接矩阵
void CreateMGraph(MGraph * G)
{    
    int i, j, k, w;
    printf("请输入图的顶点和弧的个数:\n");
    scanf("%d %d", &G->vexNum, &G->edgeNum);
    printf("请依次输入图的%d个顶点信息:\n", G->vexNum);
    for(i = 0; i < G->vexNum; i++)
        scanf("%s", &G->vexs[i]);
    for(i = 0; i < G->vexNum; i++)
    {
        for(j = 0; j < G->vexNum; j++)
        {
            if(i == j)
                G->arc[i][j] = 0;
            else
                G->arc[i][j] = INF;
        }
    }
    printf("请依次输入图的弧<Vi, Vj>上下标及对应权值:\n");
    for(k = 0; k < G->edgeNum; k++)
    {
        scanf("%d %d %d", &i, &j, &w);
        G->arc[i][j] = w;
    }
}
// 打印图的邻接矩阵
void PrintMGraph(MGraph G)
{
    int i, j;
    printf("图的邻接矩阵为:\n");
    for(i = 0; i < G.vexNum; i++)
        printf("\t%s", G.vexs[i]);
    printf("\n");
    for(i = 0; i < G.vexNum; i++)
    {
        printf("%s\t", G.vexs[i]);
        for(j = 0; j < G.vexNum; j++)
        {    
            if(G.arc[i][j] == INF)
                printf("∞\t");
            else
                printf("%d\t", G.arc[i][j]);
        }
        printf("\n");
    }
}
//最短路径-弗洛伊德算法
void Floyd(MGraph G, int ** path, int ** dist)
{    
    int i, j, k;
    for(i = 0; i < G.vexNum; i++)
    {
        for(j = 0; j < G.vexNum; j++)
        {
            dist[i][j] = G.arc[i][j];//初始为两顶点间对应权值
            path[i][j] = j;//初始为经过顶点下标
        }
    }
    for(k = 0; k < G.vexNum; k++)
    {
        for(i = 0; i < G.vexNum; i++)
        {
            for(j = 0; j < G.vexNum; j++)
            {    
                //若经过新顶点K路径比原路径更短,则更新最短路径并记录经过下标为k的顶点
                if(dist[i][j] > dist[i][k] + dist[k][j])
                {
                    dist[i][j] = dist[i][k] + dist[k][j];
                    path[i][j] = path[i][k];
                }
            }
        }
    }
}
//打印最短路径
void PrintRoad(MGraph G, int ** path, int ** dist)
{
    int i, j, k;
    printf("最终dist数组为:\n");
    for(i = 0; i < G.vexNum; i++)
    {
        for(j = 0; j < G.vexNum; j++)
        {    
            if(dist[i][j] != INF)
                printf("\t%d", dist[i][j]);
            else
                printf("\t∞");
        }
        printf("\n");
    }
    printf("最终path数组为:\n");
    for(i = 0; i < G.vexNum; i++)
    {
        for(j = 0; j < G.vexNum; j++)
        {
            printf("\t%d", path[i][j]);
        }
        printf("\n");
    }
    printf("各顶点间的最短路径和权值和为:\n");
    for(i = 0; i < G.vexNum; i++)
    {    
        for(j = 0; j < G.vexNum; j++)
        {    
            printf("%s-%s:\t", G.vexs[i], G.vexs[j]);
            printf("%s-->", G.vexs[i]);
            k = path[i][j];//找到下一个顶点
            while(k != j)//循环打印路径点直到找到终点
            {    
                printf("%s-->", G.vexs[k]);
                k = path[k][j];//找到下一个顶点
            }
            printf("%s-->", G.vexs[j]);//打印终点
            if(dist[i][j] != INF)
                printf("(%d)\n", dist[i][j]);
            else
                printf("(∞)\n");
        }
        printf("\n");
    }
}
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值