最短路径 (单源最短路径Dijkstra和任意两点最短路径Floyd) C实现

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define MAX_VERTEX_NUM 20
#define INFINITY INT_MAX

typedef struct MGraph
{
    int vexnum, arcnum;
    int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    char verx[MAX_VERTEX_NUM];
}MGraph, *PMGraph;


PMGraph CreateMGraph()
{
    char verx[3] = { 'a', 'b', 'c'};
    int arcs[3][3] = {
        { 0, 4, 11 },
        { 6, 0, 2 },
        { 3, INFINITY, 0 }

    };

    PMGraph pmgraph = (PMGraph)malloc(sizeof(MGraph));
    //printf("输入顶点数和边数:");
    //scanf("%d %d", &pmgraph->vexnum, &pmgraph->arcnum);
    //getchar();

    pmgraph->arcnum = 5;       //边数
    pmgraph->vexnum = 3;       //顶点数

    for (int i = 0; i < pmgraph->vexnum; i++)
    {
    //  printf("输入第 %d 个顶点名称:",i);
    //  scanf("%c", &pmgraph->verx[i]);
    //  getchar();
        pmgraph->verx[i] = verx[i];
    }

    for (int i = 0; i < pmgraph->vexnum; i++)
    {
        for (int j = 0; j < pmgraph->vexnum; j++)
            pmgraph->arcs[i][j] = arcs[i][j];
    }

    //printf("输入边的两个顶点及权值:\n");
    //int u = 0, v = 0, w = 0;
    //for (int i = 0; i < pmgraph->arcnum; i++)
    //{
    //  printf("输入第 %d 条边:", i);
    //  scanf("%d %d %d", &u, &v, &w);
    //  pmgraph->arcs[u][v] = w;
    //  getchar();
    //}

    return pmgraph;
}


void PrintMGraph(PMGraph pmgraph)
{
        for (int i = 0; i < pmgraph->vexnum; i++)
        {
            for (int j = 0; j < pmgraph->vexnum; j++)
            {
                if (pmgraph->arcs[i][j] != INFINITY)
                {
                    printf("%d  ", pmgraph->arcs[i][j]);
                }
                else
                {
                    printf("∞ ");
                }
            }
            printf("\n");
        }
}


//单源最短路径
void Dijkstra(PMGraph pmgraph, int v0)
{
    bool final[MAX_VERTEX_NUM];   //final[v]=true 表示以求得从v0到v的最短路径、
    bool path[MAX_VERTEX_NUM][MAX_VERTEX_NUM];  //P[v][w]=true,则w是v0到v最短路径上的顶点
    int D[MAX_VERTEX_NUM];   //D[v]表示顶点v0到v的最短路径长度

    for (int v = 0; v < pmgraph->vexnum; v++)
    {
        final[v] = false;
        D[v] = pmgraph->arcs[v0][v];

        for (int w = 0; w < pmgraph->vexnum; w++)
        {
            path[v][w] = false;
        }

        if (D[v] < INFINITY)
        {
            path[v][v0] = true;
            path[v][v] = true;
        }
    }

    final[v0] = true;
    D[v0] = 0;
    int min = INFINITY, k = 0, tmp = 0;

    for (int i = 1; i < pmgraph->vexnum; i++)
    {
        min = INFINITY;
        for (int w = 0; w < pmgraph->vexnum; w++)
        {
            if (!final[w])
            {
                if (D[w] < min)
                {
                    k = w;
                    min = D[w]; 
                }
            }
        }
        final[k] = true;

        for (int w = 0; w < pmgraph->vexnum; w++)
        {
            tmp = pmgraph->arcs[k][w] == INFINITY ? INFINITY : (min + pmgraph->arcs[k][w]);
            if (!final[w] && (tmp < D[w]))
            {
                D[w] = min + pmgraph->arcs[k][w];
                path[w][k] = true;
                path[w][w] = true;
            }
        }

    }

    for (int i = 0; i < pmgraph->vexnum; i++)
    {
        if (D[i] != INFINITY)
        {
            printf("%d: %d ----", i, D[i]);
            for (int j = 0; j < pmgraph->vexnum; j++)
            {
                if (path[i][j])
                    printf("%d  ", j);
            }
            printf("\n");
        }
    }
}


//任意两点之间最短路径
void Floyd(PMGraph pmgraph)
{
    int D[MAX_VERTEX_NUM][MAX_VERTEX_NUM];                 //D[v][w]表示顶点v,w之间的路径最短路径长度
    bool P[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM];  //P[v][w][u]表示顶点u为v,w最短路径上的顶点

    for (int v = 0; v < pmgraph->vexnum; v++)
    {
        for (int w = 0; w < pmgraph->vexnum; w++)
        {
            D[v][w] = pmgraph->arcs[v][w];
            for (int u = 0; u < pmgraph->vexnum; u++)
            {
                P[v][w][u] = false;
            }

            if (D[v][w] < INFINITY)
            {
                P[v][w][v] = true;
                P[v][w][w] = true;
            }
        }
    }

    for (int u = 0; u < pmgraph->vexnum; u++)
    {
        for (int v = 0; v < pmgraph->vexnum; v++)
        {
            for (int w = 0; w < pmgraph->vexnum; w++)
            {
                int tmp = (D[v][u] < INFINITY && D[u][w] < INFINITY) ? D[v][u] + D[u][w]  : INFINITY;
                if (tmp < D[v][w])
                {
                    D[v][w] = D[v][u] + D[u][w];
                    for (int i = 0; i < pmgraph->vexnum; i++)
                        P[v][w][u] = P[v][u][i] || P[u][w][i];
                }
            }
        }
    }


    for (int v = 0; v < pmgraph->vexnum; v++)
    {
        for (int w = 0; w < pmgraph->vexnum; w++)
        {
            if (D[v][w] < INFINITY)
            {
                printf("%d--%d ; %d parh:", v, w, D[v][w]);
                for (int u = 0; u < pmgraph->vexnum; u++)
                {
                    if (P[v][w][u])
                    {
                        printf("%d  ", u);
                    }
                }
                printf("\n");
            }else
            {
                printf("%d--%d ; ∞\n", v, w);
            }

        }
    }
}


int main()
{
    PMGraph pmgraph = CreateMGraph();
    PrintMGraph(pmgraph);
    Dijkstra(pmgraph,0);
    printf("\n");
    Floyd(pmgraph);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值