Floyd算法

本文详细介绍Floyd算法的基本思想及其实现过程,通过遍历所有节点来寻找任意两点间的最短路径,并提供完整的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点到B,所以,我们假设dist(AB)为节点A到节点B的最短路径的距离,对于每一个节点K,我们检查dist(AK) + dist(KB) < dist(AB)是否成立,如果成立,证明从A到K再到B的路径比A直接到B的路径短,我们便设置 dist(AB) = dist(AK) + dist(KB),这样一来,当我们遍历完所有节点K,dist(AB)中记录的便是A到B的最短路径的距离。

// Floyd.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"

#define MaxVertexNum 100
#define INFINITY 65535
typedef int Vertex;
typedef char DataType;
typedef int WeightType;

typedef struct ENode *PtrToENode;
struct ENode {
    Vertex V1, V2;
    WeightType Weight;
};
typedef PtrToENode Edge;

typedef struct GNode *PtrToGNode;
struct GNode {
    int Nv;
    int Ne;
    WeightType G[MaxVertexNum][MaxVertexNum];
    DataType Data[MaxVertexNum];
};
typedef PtrToGNode MGraph;

MGraph CreateGraph(int VertexNum)
{
    Vertex V, W;
    MGraph Graph;
    Graph = (MGraph)malloc(sizeof(struct GNode));
    Graph->Nv = VertexNum;
    Graph->Ne = 0;
    for (V = 0; V<VertexNum; V++) {
        for (W = 0; W<VertexNum; W++)
            Graph->G[V][W] = INFINITY;
    }
    return Graph;
}

void InsertEdge(MGraph Graph, Edge E)
{
    Graph->G[E->V1][E->V2] = E->Weight;
    /*若为无向图,则还需要*/
    //Graph->G[E->V2][E->V1] = E->Weight;
}

MGraph BuildGraph()
{
    MGraph Graph;
    Edge E;
    int Nv;
    Vertex i;
    printf("input the number of Vertex\n");
    scanf_s("%d", &Nv);
    Graph = CreateGraph(Nv);
    scanf_s("%d", &Graph->Ne);
    if (Graph->Ne != 0) {
        E = (Edge)malloc(sizeof(struct ENode));
        for (i = 0; i<Graph->Ne; i++) {
            scanf_s("%d %d %d", &E->V1, &E->V2, &E->Weight);
            InsertEdge(Graph, E);
        }
    }
    return Graph;
}

void Floyd(MGraph Graph, int **D,int **path)
{
    /*初始化有直接相连的两个结点的path,path为出发点*/
    for(int i=0;i<Graph->Nv;i++)
        for (int j = 0; j < Graph->Nv; j++) {
            if (Graph->G[i][j] < INFINITY)
                path[i][j] = i;
            else
                path[i][j] = -1;/*不相邻则默认无path*/
        }

    /*初始化D矩阵*/
    for (int i = 0; i<Graph->Nv; i++)
        for (int j = 0; j < Graph->Nv; j++) {
            D[i][j] = Graph->G[i][j];
        }

    /*运算最短路径,每次从k开始,是因为每次开始都需要更新两个结点之间的dist,如果k放在后面循环,则会
    过早的把i到j的最短路径确定下来了,而当后面存在更短的路径时,已经不再会更新了*/
    int k, i, j;
    for (k = 0; k < Graph->Nv; k++)
        for (i = 0; i < Graph->Nv; i++)
            for (j = 0; j < Graph->Nv; j++)
                if (D[i][k] + D[k][j] < D[i][j]) {
                    D[i][j] = D[i][k] + D[k][j];
                    path[i][j] = k;
                }
}

void printpath(int**path,int begin,int end)
{
    while (path[begin][end] != begin) {
        printf("%d ", path[begin][end]);
        end = path[begin][end];
    }
}

/*堆栈打印路径*/
/*
void printpath(int**path, int begin, int end)
{
    if (path[begin][end] != begin) {
        printpath(path, begin, path[begin][end]);
        printf("%d", path[begin][end]);
    }

    else
        printf("%d",begin);
}

*/

int main()
{
    MGraph Graph;
    Graph = BuildGraph();
    int **D;
    D = (int **)malloc(sizeof(int*)*Graph->Nv);
    for (int i = 0; i < Graph->Nv; i++)
        D[i] =(int*) malloc(sizeof(int)*Graph->Nv);
    int **path = (int**)malloc(sizeof(int*)*Graph->Nv);
    for (int i = 0; i < Graph->Nv; i++)
        path[i] = (int *)malloc(sizeof(int)*Graph->Nv);

    printf("Floyd begin\n");
    Floyd(Graph, D,path);
    printf("Floyd end\n");
    printf("mindist\n");
    for (int i = 0; i < Graph->Nv; i++)
        for (int j = 0; j < Graph->Nv; j++)
            printf("%d ", D[i][j]);
    printf("\n");
    printf("path\n");
    for (int i = 0; i < Graph->Nv; i++)
        for (int j = 0; j < Graph->Nv; j++)
            printf("%d ", path[i][j]);

    printf("printpath,input begin and end\n");
    int begin, end;
    scanf_s("%d %d", &begin, &end);
    printpath(path, begin, end);

    for(int i = 0;i<Graph->Nv;i++)
        free(D[i]);
    free(D);
    for (int i = 0; i<Graph->Nv; i++)
        free(path[i]);
    free(path);

    system("pause");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值