“chaos”的算法--之Floyd算法详解(求最短路径)
? 倘若我們要在計(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; ?
}
本文轉(zhuǎn)自 驛落黃昏 51CTO博客,原文鏈接:http://blog.51cto.com/yiluohuanghun/879900,如需轉(zhuǎn)載請(qǐng)自行聯(lián)系原作者
總結(jié)
以上是生活随笔為你收集整理的“chaos”的算法--之Floyd算法详解(求最短路径)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 配置EIGRP默认路由
- 下一篇: Cesium学习笔记(四)Camera