最短路径

最短路径有两种算法:Dijkstra(迪杰斯特拉算法)和Floyd(佛洛伊德)算法
Dijkstra算法:类似于Prim算法,通过在已经遍历到的边中寻找到最小值,不同的是Prim算法寻找的是边权值最小的值,Dijkstra算法找的是权值和最小的值。
Floyd算法:通过遍历整个结点,循环寻找每个 顶点到每个顶点的最小权值。
首选:Dijkstra算法,当需要求每个顶点到每个顶点的最短路径时,Floyd算法可以考虑。
#include <stdio.h>
#include <string.h>

#define MAXVALUE    50
#define INITVALUE   65535
#define INITPOS     0

typedef struct
{
    char Vex[MAXVALUE];
    int Arch[MAXVALUE][MAXVALUE];
    int numVexs, numArch;
}Graph;

void CreatGraph (Graph *G)
{
    int i, j, k, weight;
    printf("Enter numVexs && numArch:");
    scanf("%d%d", &(G->numVexs), &(G->numArch));
    for(i = 0; i  < G->numVexs; i++)        // 邻接矩阵初始化
    {
        for(j = 0; j < G->numVexs; j++)
        {
            G->Arch[i][j] = INITVALUE;
        }
    }
    for(k = 0; k < G->numVexs; k++)
    {
        printf("Enter %d vex:", k);
        scanf("%c", &(G->Vex[k]));
        getchar();
    }
    for(k = 0; k < G->numArch; k++)
    {
        printf("Enter i, j, &weight:");
        scanf("%d%d%d", &i, &j, &weight);
        G->Arch[i][j] = weight;
        G->Arch[j][i] = weight;
    }
}

void PrintGraph (Graph G)
{
    int i, j;
    for(i = 0; i  < G.numVexs; i++)
    {
        for(j = 0; j < G.numVexs; j++)
        {
            printf("%d ", G.Arch[i][j]);
        }
        printf("\n");
    }
}


void ShortestPath_Dijkstra (Graph G, int *P, int *D)    //P中存储着前驱顶点坐标,D总存储着路径长度
{
    int i, min, j, k;
    int final[MAXVALUE];
    P[INITPOS] = 0;
    D[INITPOS] = 0;
    final[INITPOS] = 1;
    for(i = 1; i < G.numVexs; i++)
    {
        P[i] = INITPOS;                             //可以根据算法要求到不同起始点的距离变化
        D[i] = G.Arch[INITPOS][i];
        final[i] = 0;
    }
    for(i = 0; i < G.numVexs; i++)
    {
        min = INITVALUE;
        j = 1;
        while(j < G.numVexs)
        {
            if(!final[j] && D[j] < min )
            {
                min = D[j];
                k = j;
            }
            j++;
        }
        final[k] = 1;
        for(j = 0; j < G.numVexs; j++)
        {
            if(!final[j] && D[j] > min + G.Arch[k][j])       //当遍历到比当前路径小的路径时进行替换
            {
                D[j] = min+G.Arch[k][j];
                P[j] = k;
            }
        }
    }
}

void PrintShortestPath_Dijkstra (Graph G, int *P, int *D)    //打印出有Dijkstra算法计算出的最短路径
{
    int i, p;
    for(i = 0; i < G.numVexs; i++)        //打印出路径信息
    {
        printf("(%d ", i);
        p = P[i];
        while(p)
        {
            printf("%d ", p);
            p = P[p];
        }
        printf("%d)%d\n", p, D[i]);
    }
}

void ShortestPath_Floyd (Graph G, int P[MAXVALUE][MAXVALUE], int D[MAXVALUE][MAXVALUE])
{
    int i, j, k;
    for(i = 0; i < G.numVexs; i++)
    {
        for(j = 0; j < G.numVexs; j++)
        {
            D[i][j] = G.Arch[i][j];
            P[i][j] = j;
        }
    }
    for(i = 0; i < G.numVexs; i++)
    {
        for(j = 0; j < G.numVexs; j++)
        {
            for(k = 0; k < G.numVexs; k++)
            {
                if(G.Arch[j][k] > G.Arch[j][i] + G.Arch[i][k])
                {
                    G.Arch[j][k] = G.Arch[j][i] + G.Arch[i][k];
                    P[j][k] = P[j][i];
                }
            }
        }
    }
}

void PrintShortestPath_Floyd (Graph G, int P[MAXVALUE][MAXVALUE], int D[MAXVALUE][MAXVALUE])      //打印出有Floyd
{
    int i, j, p;
    for(i = 0; i < G.numVexs; i++)
    {
        for(j = i+1; j < G.numVexs; j++)
        {
            printf("(%d ", i);
            p = P[i][j];
            while(p != j)
            {
                printf("%d ", p);
                p = P[p][j];
            }
            printf("%d)%d\n", p, D[i][j]);
        }
    }
}

int main ()
{
    Graph G;
    int P1[MAXVALUE], D1[MAXVALUE];
    int P2[MAXVALUE][MAXVALUE], D2[MAXVALUE][MAXVALUE];
    CreatGraph(&G);
    PrintGraph(G);
    ShortestPath_Dijkstra(G, P1, D1);
    PrintShortestPath_Dijkstra(G, P1, D1);
    ShortestPath_Floyd(G, P1, D2);
    PrintShortestPath_Floyd(G, P1, D2);
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值