日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

“chaos”的算法--之Floyd算法详解(求最短路径)

發(fā)布時(shí)間:2025/3/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 “chaos”的算法--之Floyd算法详解(求最短路径) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? 倘若我們要在計(jì)算機(jī)上建立一個(gè)交通咨詢系統(tǒng)則可以采用圖的結(jié)構(gòu)來(lái)表示實(shí)際的交通網(wǎng)絡(luò)。其實(shí)現(xiàn)最基本的功能,求出任意兩點(diǎn)間的最短路徑,

? 求最短路徑的經(jīng)典方法有很多種,最常用的便是迪杰斯特拉算法和佛洛依德(Floyd)算法,這篇文章就著重介紹Floyd算法。

? ?求兩點(diǎn)之間的最短路徑無(wú)外乎有兩種情況,一種就是從一點(diǎn)直接到另一點(diǎn),另一種就是從一點(diǎn)經(jīng)過(guò)n個(gè)節(jié)點(diǎn)后再到另一個(gè)節(jié)點(diǎn),比如說(shuō)要從A到B,則有兩種情況就是A直接到B,或者是從A經(jīng)過(guò)N個(gè)節(jié)點(diǎn)后再到B,所以,我們假設(shè)Dis(AB)為節(jié)點(diǎn)A到節(jié)點(diǎn)B的最短路徑的距離,對(duì)于每一個(gè)節(jié)點(diǎn)X,我們檢查Dis(AX)+Dis(XB)<Dis(AB)是否成立,如果成立,證明從A再到B的路徑比A直接到B的路徑短,我們便設(shè)置Dis(AB)=Dis(AX)+Dis(XB),這樣一來(lái),當(dāng)我們遍歷完所有節(jié)點(diǎn)X,Dis(AB)中記錄的便是A到B的最短路徑的距離。

直接上代碼:

  • for(k = 0; k < Number; ++k) ?

  • ? ?{ ?

  • for(i = 0; i < Number; ++i) ?

  • ? ? ? ?{ ?

  • for(j = 0; j < Number; ++j) ?

  • ? ? ? ? ? ?{ ?

  • if((Dis[i][k] + Dis[k][j]) < Dis[i][j]) ?

  • ? ? ? ? ? ? ? ?{ ?

  • // 找到更短路徑 ?

  • ? ? ? ? ? ? ? ? ? ?Dis[i][j] = Dis[i][k] + Dis[k][j]; ?

  • ? ? ? ? ? ? ? ?} ?

  • ? ? ? ? ? ?} ?

  • ? ? ? ?} ?

  • }

  • 那么接下來(lái)的問(wèn)題就是,我們?nèi)绾握页鲎疃搪窂侥?#xff1f;這里需要借助一個(gè)輔助數(shù)組Path,它是這樣使用的:Path(AB)的值如果為P,則表示A節(jié)點(diǎn)到B節(jié)點(diǎn)的最短路徑是A->...->P->B。這樣一來(lái),假設(shè)我們要找A->B的最短路徑,那么就依次查找,假設(shè)Path(AB)的值為P,那么接著查找Path(AP),假設(shè)Path(AP)的值為L(zhǎng),那么接著查找Path(AL),假設(shè)Path(AL)的值為A,則查找結(jié)束,最短路徑為A->L->P->B。

    那么,如何填充Path的值呢?很簡(jiǎn)單,當(dāng)我們發(fā)現(xiàn)Dis(AX) + Dis(XB) < Dis(AB)成立時(shí),就要把最短路徑改為A->...->X->...->B,而此時(shí),Path(XB)的值是已知的,所以,Path(AB) = Path(XB)。

    下面的就是代碼的具體實(shí)現(xiàn)了:


  • CreateGraphDemo.h ?

  • #ifndef __CREATE_GRAPH_DEMO_H

  • #define __CREATE_GRAPH_DEMO_H

  • #include <stdio.h>

  • #include <stdlib.h>

  • #include <string.h>

  • #ifndef false

  • #define false 0

  • #endif

  • #ifndef true

  • #define true 1

  • #endif

  • #ifndef error

  • #define error -1

  • #endif

  • #define INFINITY ? ?INT_MAX

  • #define MAX_VERTEX_NUM ?20

  • #define MAX_INFO 100

  • #define MAX_NAME 10

  • typedefint VRType; ?

  • typedefchar InfoType; ?

  • typedefchar* VertexType; ?

  • VRType visited[MAX_VERTEX_NUM]; ?

  • typedefenum{DG, DN, UDG, UDN} GraphKind; ?

  • typedefstruct ArcCell ?

  • { ?

  • ? ?VRType ?adj;//VRType是頂點(diǎn)關(guān)系類型,對(duì)無(wú)權(quán)圖,用1或0表示相鄰否,對(duì)帶權(quán)圖,則為權(quán)值類型

  • ? ?InfoType *info;//該弧相關(guān)信息的指針

  • }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; ?

  • typedefstruct

  • { ?

  • ? ?VertexType ?vexs[MAX_VERTEX_NUM]; ? ? ? // 頂點(diǎn)向量

  • ? ?AdjMatrix ? arcs; ? ? ? ? ? ? ? ? ? ? ? // 鄰接矩陣

  • ? ?VRType ? ? ?vexnum, arcnum; ? ? ? ? ? ? // 圖的當(dāng)前頂點(diǎn)數(shù)和弧數(shù)

  • ? ?GraphKind ? kind; ? ? ? ? ? ? ? ? ? ? ? // 圖的種類標(biāo)志

  • }MGraph; ?

  • //棧的結(jié)構(gòu)

  • typedefstruct

  • { ?

  • ? ?VRType *base; ?

  • ? ?VRType *top; ?

  • }SqStack; ?

  • #ifdef __cplusplus

  • extern"C"{ ?

  • #endif

  • //返回指定頂點(diǎn)elem在頂點(diǎn)向量中的位置

  • int LocateVex(MGraph G, VertexType elem); ?

  • //創(chuàng)建無(wú)向網(wǎng)

  • int CreateUDN(MGraph *G); ?

  • //創(chuàng)建有向圖

  • int CreateDN(MGraph *G); ?

  • //顯示其對(duì)應(yīng)的鄰接矩陣

  • int Display(MGraph *G); ?

  • //顯示景點(diǎn)

  • int DisplayVexs(MGraph *G); ?

  • //釋放空間

  • int FreeGraph(MGraph **G); ?

  • //最短路徑算法

  • void FloydMethods(int Dis[][MAX_VERTEX_NUM], int Path[][MAX_VERTEX_NUM], int vexnum); ?

  • //輸出最短路徑以及路徑長(zhǎng)度

  • void ShowShortPath(int Dis[][MAX_VERTEX_NUM], int Path[][MAX_VERTEX_NUM], SqStack *S, MGraph *G); ?

  • //初始化棧

  • int InitStack(SqStack *S); ?

  • //壓棧操作

  • int Push(SqStack *S, int e); ?

  • //出棧操作

  • int Pop(SqStack *S, int *e); ?

  • #ifdef _cplusplus

  • } ?

  • #endif

  • #endif

  • //CreateGraphDemo.c

  • #include "CreateGraphDemo.h"

  • int visited[20]; ?

  • //返回指定頂點(diǎn)在頂點(diǎn)向量中的位置

  • int LocateVex(MGraph G, VertexType elem) ?

  • { ?

  • int i; ?

  • for(i = 0; i < G.vexnum; ++i) ?

  • if(strcmp(elem, G.vexs[i]) == 0) ?

  • return i; ?

  • return error; ?

  • } ?

  • void FloydMethods(int Dis[][MAX_VERTEX_NUM], int Path[][MAX_VERTEX_NUM], int _nVertexCount) ?

  • { ?

  • int i, j, k; ?

  • // 先初始化Path ?

  • for(i = 0; i < _nVertexCount; ++i) ?

  • ? ?{ ?

  • for(j = 0; j < _nVertexCount; ++j) ?

  • ? ? ? ?{ ?

  • ? ? ? ? ? ?Path[i][j] = i; ?

  • ? ? ? ?} ?

  • ? ?} ?

  • for(k = 0; k < _nVertexCount; ++k) ?

  • ? ?{ ?

  • for(i = 0; i < _nVertexCount; ++i) ?

  • ? ? ? ?{ ?

  • for(j = 0; j < _nVertexCount; ++j) ?

  • ? ? ? ? ? ?{ ?

  • if((Dis[i][k] + Dis[k][j]) < Dis[i][j]) ?

  • ? ? ? ? ? ? ? ?{ ?

  • // 找到更短路徑 ?

  • ? ? ? ? ? ? ? ? ? ?Dis[i][j] = Dis[i][k] + Dis[k][j]; ?

  • ? ? ? ? ? ? ? ? ? ?Path[i][j] = Path[k][j]; ?

  • ? ? ? ? ? ? ? ?} ?

  • ? ? ? ? ? ?} ?

  • ? ? ? ?} ?

  • ? ?} ?

  • } ?

  • void ShowShortPath(int Dis[][MAX_VERTEX_NUM], int Path[][MAX_VERTEX_NUM], SqStack *S, ?MGraph *G) ?

  • { ?

  • int i, j, e, t, m, len = 0; ?

  • char Name1[10], Name2[10]; ?

  • ? ?printf("\n請(qǐng)輸入你想查找的兩個(gè)景點(diǎn)名稱 (兩景點(diǎn)間用空格隔開(kāi)) : ?"); ?

  • ? ?scanf("%s %s", Name1, Name2); ?

  • ? ?printf("起源 -> 目的地 ? 最小距離 ? ? ? ?最短路徑\n"); ?

  • for(i = 0; i < G->vexnum; ++i) ?

  • ? ?{ ?

  • for(j = 0; j < G->vexnum; ++j) ?

  • ? ? ? ?{ ?

  • if(!strcmp(Name1, (*G).vexs[i]) && !strcmp(Name2, (*G).vexs[j])) ?

  • ? ? ? ? ? ?{ ?

  • ? ? ? ? ? ? ? ?printf("%s -> %s\t", (*G).vexs[i], (*G).vexs[j]); ?

  • if(1000 == Dis[i][j]) ? ?// i -> j 不存在路徑 ?

  • ? ? ? ? ? ? ? ?{ ?

  • ? ? ? ? ? ? ? ? ? ?printf("%s-->>%s is no road\n", (*G).vexs[i], (*G).vexs[j]);; ?

  • ? ? ? ? ? ? ? ?} ?

  • else

  • ? ? ? ? ? ? ? ?{ ?

  • ? ? ? ? ? ? ? ? ? ?printf(" ? ? %d\t\t", Dis[i][j]); ?

  • int k = j; ?

  • do

  • ? ? ? ? ? ? ? ? ? ?{ ?

  • ? ? ? ? ? ? ? ? ? ? ? ?k = Path[i][k]; ?

  • ? ? ? ? ? ? ? ? ? ? ? ?Push(S, k); ?

  • ? ? ? ? ? ? ? ? ? ? ? ?len++; ?

  • ? ? ? ? ? ? ? ? ? ?}while(k != i); ?

  • ? ? ? ? ? ? ? ? ? ?Pop(S, &e); ?

  • ? ? ? ? ? ? ? ? ? ?printf("%s", (*G).vexs[e]); ?

  • ? ? ? ? ? ? ? ? ? ?t = e; ?

  • for(m = 0; m < len ; m++) ?

  • ? ? ? ? ? ? ? ? ? ?{ ?

  • ? ? ? ? ? ? ? ? ? ? ? ?Pop(S, &e); ?

  • if(t != e) ?

  • ? ? ? ? ? ? ? ? ? ? ? ?{ ?

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?printf(" -> %s", (*G).vexs[e]); ?

  • ? ? ? ? ? ? ? ? ? ? ? ?} ?

  • ? ? ? ? ? ? ? ? ? ? ? ?t = e; ? ? ? ? ? ? ? ? ? ? ? ?

  • ? ? ? ? ? ? ? ? ? ?} ?

  • ? ? ? ? ? ? ? ? ? ?printf(" -> %s\n", (*G).vexs[j]); ?

  • ? ? ? ? ? ? ? ?} ?

  • ? ? ? ? ? ?} ?

  • ? ? ? ?} ?

  • ? ?} ?

  • } ?

  • int InitStack(SqStack *S) ?

  • { ?

  • ? ?S->base = (int *)malloc(50*sizeof(int)); ?

  • if(!S->base) ?

  • return error; ?

  • ? ?S->top = S->base; ?

  • returntrue; ?

  • } ?

  • int Push(SqStack *S, int e) ?

  • { ?

  • ? ?*(S->top++) = e; ?

  • returntrue; ?

  • } ?

  • int Pop(SqStack *S, int *e) ?

  • { ?

  • if(S->top == S->base) ?

  • returnfalse; ?

  • ? ?*e = *(--(S->top)); ?

  • returntrue; ?

  • } ?

  • //無(wú)向網(wǎng)

  • int CreateUDN(MGraph *G) ?

  • { ?

  • int i, j, k, l, IncInfo, w;//IncInfo表示弧是否有其他信息

  • char s[MAX_INFO], *info; ?

  • char va[10], vb[10]; ?

  • ? ?printf("請(qǐng)輸入校園中的景點(diǎn)個(gè)數(shù),所有景點(diǎn)之間的馬路條數(shù),景點(diǎn)是否含有其他信息(是:1,否:0)"); ?

  • ? ?scanf("%d,%d,%d", &(*G).vexnum, &(*G).arcnum, &IncInfo); ?

  • ? ?printf("請(qǐng)輸入每個(gè)景點(diǎn)的名稱(<%d個(gè)字符):\n", MAX_NAME); ?

  • for(i = 0; i < (*G).vexnum; ++i)//構(gòu)造頂點(diǎn)向量

  • ? ?{ ?

  • ? ? ? ?(*G).vexs[i] = (VertexType)malloc(sizeof(char)*MAX_NAME); ?

  • ? ? ? ?scanf("%s", (*G).vexs[i]); ?

  • ? ? ? ?getchar(); ?

  • ? ?} ?

  • for(i = 0; i < (*G).vexnum; ++i)//初始化鄰接矩陣

  • ? ?{ ?

  • for(j = 0; j < (*G).vexnum; ++j) ?

  • ? ? ? ?{ ?

  • ? ? ? ? ? ?(*G).arcs[i][j].adj = 1000; ?

  • ? ? ? ? ? ?(*G).arcs[i][j].info = NULL; ?

  • ? ? ? ?} ?

  • ? ?} ?

  • ? ?printf("請(qǐng)輸入%d條路中每條路所連接的兩個(gè)景點(diǎn)(以空格隔開(kāi)): \n", (*G).arcnum); ?

  • for(k = 0; k < (*G).arcnum; ++k) ?

  • ? ?{ ?

  • ? ? ? ?scanf("%s %s", va, vb);//輸入弧頭,弧尾信息

  • ? ? ? ?printf("請(qǐng)輸入該條路的長(zhǎng)度 : "); ?

  • ? ? ? ?scanf("%d", &w); ?

  • ? ? ? ?i = LocateVex(*G, va);//定位弧尾位置,

  • ? ? ? ?j = LocateVex(*G, vb);//定位弧頭位置

  • ? ? ? ?(*G).arcs[i][j].adj = w;//權(quán)值大小

  • ? ? ? ?(*G).arcs[j][i].adj = w; ?

  • if(IncInfo) ?

  • ? ? ? ?{ ?

  • ? ? ? ? ? ?printf("請(qǐng)輸入該景點(diǎn)的相關(guān)信息(<%d個(gè)字符) : ", MAX_INFO); ?

  • ? ? ? ? ? ?scanf("%s", s); ?

  • ? ? ? ? ? ?l = strlen(s); ?

  • if(l) ?

  • ? ? ? ? ? ?{ ?

  • ? ? ? ? ? ? ? ?(*G).arcs[i][j].info = (char *)malloc((l+1)*sizeof(char)); ?

  • ? ? ? ? ? ? ? ?strcpy((*G).arcs[i][j].info, s); ?

  • ? ? ? ? ? ?} ?

  • ? ? ? ?} ?

  • ? ?} ?

  • ? ?(*G).kind = DN; ?

  • returntrue; ?

  • } ?

  • //有向網(wǎng)

  • int CreateDN(MGraph *G) ?

  • { ?

  • int i, j, k, l, IncInfo, w;//IncInfo表示弧是否有其他信息

  • char s[MAX_INFO], *info; ?

  • char va[5], vb[5]; ?

  • ? ?printf("請(qǐng)輸入校園中的景點(diǎn)個(gè)數(shù),所有景點(diǎn)之間的馬路條數(shù),景點(diǎn)是否含有其他信息(是:1,否:0)"); ?

  • ? ?scanf("%d,%d,%d", &(*G).vexnum, &(*G).arcnum, &IncInfo); ?

  • ? ?printf("請(qǐng)輸入每個(gè)景點(diǎn)的名稱(<%d個(gè)字符)\n", MAX_NAME); ?

  • for(i = 0; i < (*G).vexnum; ++i)//構(gòu)造頂點(diǎn)向量

  • ? ?{ ?

  • ? ? ? ?(*G).vexs[i] = (VertexType)malloc(sizeof(char)*5); ?

  • ? ? ? ?scanf("%s", (*G).vexs[i]); ?

  • ? ? ? ?getchar(); ?

  • ? ?} ?

  • for(i = 0; i < (*G).vexnum; ++i)//初始化鄰接矩陣

  • for(j = 0; j < (*G).vexnum; ++j) ?

  • ? ? ? ?{ ?

  • ? ? ? ? ? ?(*G).arcs[i][j].adj = 1000; ?

  • ? ? ? ? ? ?(*G).arcs[i][j].info = NULL; ?

  • ? ? ? ?} ?

  • ? ?printf("請(qǐng)輸入%d條路中每條路所連接的兩個(gè)景點(diǎn)(以空格隔開(kāi)): \n", (*G).arcnum); ?

  • for(k = 0; k < (*G).arcnum; ++k) ?

  • ? ?{ ?

  • ? ? ? ?scanf("%s %s", va, vb);//輸入弧頭,弧尾信息

  • ? ? ? ?printf("請(qǐng)輸入該條路的長(zhǎng)度 : "); ?

  • ? ? ? ?scanf("%d", &w); ?

  • ? ? ? ?i = LocateVex(*G, va);//定位弧尾位置,

  • ? ? ? ?j = LocateVex(*G, vb);//定位弧頭位置

  • ? ? ? ?(*G).arcs[i][j].adj = w;//權(quán)值大小

  • if(IncInfo) ?

  • ? ? ? ?{ ?

  • ? ? ? ? ? ?printf("請(qǐng)輸入該景點(diǎn)的相關(guān)信息(<%d個(gè)字符) : ", MAX_INFO); ?

  • ? ? ? ? ? ?scanf("%s", s); ?

  • ? ? ? ? ? ?l = strlen(s); ?

  • if(l) ?

  • ? ? ? ? ? ?{ ?

  • ? ? ? ? ? ? ? ?(*G).arcs[i][j].info = (char *)malloc((l+1)*sizeof(char)); ?

  • ? ? ? ? ? ? ? ?strcpy((*G).arcs[i][j].info, s); ?

  • ? ? ? ? ? ?} ?

  • ? ? ? ?} ?

  • ? ?} ?

  • ? ?(*G).kind = DN; ?

  • returntrue; ?

  • } ?

  • int Display(MGraph *G) ?

  • { ?

  • int i, j; ?

  • ? ?printf("鄰接矩陣輸出 :\n"); ?

  • for(i = 0; i < G->vexnum; i++) ?

  • ? ?{ ?

  • for(j = 0; j < G->vexnum; j++) ?

  • ? ? ? ?{ ?

  • ? ? ? ? ? ?printf("%d ?", G->arcs[i][j].adj); ?

  • ? ? ? ?} ?

  • ? ? ? ?printf("\n"); ?

  • ? ?} ?

  • } ?

  • int DisplayVexs(MGraph *G) ?

  • { ?

  • int i; ?

  • ? ?printf("---------------------景點(diǎn):--------------------\n"); ?

  • for(i = 0; i < G->vexnum; ++i) ?

  • ? ?{ ?

  • ? ? ? ?printf("%s ? ", G->vexs[i]); ?

  • ? ?} ?

  • ? ?printf("\n------------------------------------------------\n\n"); ?

  • } ?

  • int FreeGraph(MGraph **G) ?

  • { ?

  • int i, j; ?

  • for(i = 0; i < (*(*G)).vexnum; i++) ?

  • ? ?{ ?

  • ? ? ? ?free((*G)->vexs[i]); ?

  • ? ? ? ?(*G)->vexs[i] = NULL; ?

  • for(j = 0; j < (*(*G)).vexnum; j++) ?

  • ? ? ? ?{ ?

  • if((*G)->arcs[i][j].info) ?

  • ? ? ? ? ? ?{ ?

  • ? ? ? ? ? ? ? ?free((*G)->arcs[i][j].info); ?

  • ? ? ? ? ? ? ? ?(*G)->arcs[i][j].info = NULL; ?

  • ? ? ? ? ? ?} ?

  • ? ? ? ?} ?

  • ? ?} ?

  • ? ?free(*G); ?

  • ? ?*G = NULL; ?

  • returntrue; ?

  • } ?

  • //main.c

  • #include "CreateGraphDemo.h"

  • int main(int argc, char *argv[]) ?

  • { ?

  • int i, j, a[20][20], b[20][20]; ?

  • char ch; ?

  • ? ?SqStack S; ?

  • ? ?MGraph **p, *G = (MGraph *)malloc(sizeof(MGraph)); ?

  • ? ?p = &G; ?

  • ? ?CreateUDN(G); ?

  • //CreateDN(G);

  • for(i = 0; i < G->vexnum; ++i) ?

  • ? ?{ ?

  • for(j = 0; j < G->vexnum; ++j) ?

  • ? ? ? ?{ ?

  • ? ? ? ? ? ?a[i][j] = G->arcs[i][j].adj; ?

  • ? ? ? ?} ?

  • ? ?} ?

  • ? ?InitStack(&S); ?

  • ? ?FloydMethods(a, b, G->vexnum); ? ?

  • loop: ?

  • ? ?DisplayVexs(G); ?

  • ? ?ShowShortPath(a, b, &S, G); ?

  • ? ?printf("Again ? (Y/N)\n"); ?

  • ? ?getchar(); ?

  • ? ?scanf("%c", &ch); ?

  • if('y' == ch || 'Y' == ch) ?

  • goto loop; ?

  • ? ?FreeGraph(p); ?

  • return 0; ?

  • }

  • 這是我之前寫(xiě)的一個(gè)校園導(dǎo)航的Demo,希望對(duì)大家有用……



    本文轉(zhuǎn)自 驛落黃昏 51CTO博客,原文鏈接:http://blog.51cto.com/yiluohuanghun/879900,如需轉(zhuǎn)載請(qǐng)自行聯(lián)系原作者

    總結(jié)

    以上是生活随笔為你收集整理的“chaos”的算法--之Floyd算法详解(求最短路径)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。