“Chaos”的算法之Floyd算法

倘若我们要在计算机上建立一个交通咨询系统则可以采用图的结构来表示实际的交通网络。其实现最基本的功能,求出任意两点间的最短路径,

求最短路径的经典方法有很多种,最常用的便是迪杰斯特拉算法和佛洛依德(Floyd)算法,这篇文章就着重介绍Floyd算法。

求两点之间的最短路径无外乎有两种情况,一种就是从一点直接到另一点,另一种就是从一点经过n个节点后再到另一个节点,比如说要从A到B,则有两种情况就是A直接到B,或者是从A经过N个节点后再到B,所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离,对于每一个节点X,我们检查Dis(AX)+Dis(XB)<Dis(AB)是否成立,如果成立,证明从A再到B的路径比A直接到B的路径短,我们便设置Dis(AB)=Dis(AX)+Dis(XB),这样一来,当我们遍历完所有节点X,Dis(AB)中记录的便是A到B的最短路径的距离。

直接上代码:

 1 /* 求各个顶点对之间的最短路径 */
 2 for (int k = 0; k < G.vtxCnt; ++k) {                // 顶点循环
 3     for (int i = 0; i < G.vtxCnt; ++i) {            // 起点循环
 4         for (int j = 0; j < G.vtxCnt; ++j) {        // 终点循环
 5             // 判断是否存在更短的路径,有,则边值矩阵和路径矩阵更新;dist[in][post]得出的是in到post的最短路径
 6             if (dist[i][j] > dist[i][k] + dist[k][j]) {
 7                 dist[i][j] > dist[i][k] + dist[k][j];
 8                 path[i][j] = path[k][j];
 9             }
10         }
11     }
12 }

  那么接下来的问题就是,我们如何找出最短路径呢?这里需要借助一个辅助数组Path,它是这样使用的:Path(AB)的值如果为P,则表示A节点到B节点的最短路径是A->...->P->B。这样一来,假设我们要找A->B的最短路径,那么就依次查找,假设Path(AB)的值为P,那么接着查找Path(AP),假设Path(AP)的值为L,那么接着查找Path(AL),假设Path(AL)的值为A,则查找结束,最短路径为A->L->P->B。

那么,如何填充Path的值呢?很简单,当我们发现Dis(AX) + Dis(XB) < Dis(AB)成立时,就要把最短路径改为A->...->X->...->B,而此时,Path(XB)的值是已知的,所以,Path(AB) = Path(XB)。

下面的就是代码的具体实现了:

 1 CreateGraphDemo.h
 2 #ifndef __CREATE_GRAPH_DEMO_H
 3 #define __CREATE_GRAPH_DEMO_H
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 #include <string.h>
 7 #ifndef false
 8 #define false 0
 9 #endif
10 #ifndef true
11 #define true 1
12 #endif
13 #ifndef error
14 #define error -1
15 #endif
16 #define INFINITY    INT_MAX
17 #define MAX_VERTEX_NUM  20
18 #define MAX_INFO 100
19 #define MAX_NAME 10
20 typedefint VRType;
21 typedefchar InfoType;
22 typedefchar* VertexType;
23 VRType visited[MAX_VERTEX_NUM];
24 typedefenum{ DG, DN, UDG, UDN } GraphKind;
25 typedefstruct ArcCell
26 {
27     VRType  adj;//VRType是顶点关系类型,对无权图,用1或0表示相邻否,对带权图,则为权值类型
28     InfoType *info;//该弧相关信息的指针
29 }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
30 typedefstruct
31 {
32     VertexType  vexs[MAX_VERTEX_NUM];       // 顶点向量
33     AdjMatrix   arcs;                       // 邻接矩阵
34     VRType      vexnum, arcnum;             // 图的当前顶点数和弧数
35     GraphKind   kind;                       // 图的种类标志
36 }MGraph;
37 //栈的结构
38 typedefstruct
39 {
40     VRType *base;
41     VRType *top;
42 }SqStack;
43 #ifdef __cplusplus
44 extern"C"{
45 #endif
46     //返回指定顶点elem在顶点向量中的位置
47     int LocateVex(MGraph G, VertexType elem);
48     //创建无向网
49     int CreateUDN(MGraph *G);
50     //创建有向图
51     int CreateDN(MGraph *G);
52     //显示其对应的邻接矩阵
53     int Display(MGraph *G);
54     //显示景点
55     int DisplayVexs(MGraph *G);
56     //释放空间
57     int FreeGraph(MGraph **G);
58     //最短路径算法
59     void FloydMethods(int Dis [][MAX_VERTEX_NUM], int Path [][MAX_VERTEX_NUM], int vexnum);
60     //输出最短路径以及路径长度
61     void ShowShortPath(int Dis [][MAX_VERTEX_NUM], int Path [][MAX_VERTEX_NUM], SqStack *S, MGraph *G);
62     //初始化栈
63     int InitStack(SqStack *S);
64     //压栈操作
65     int Push(SqStack *S, int e);
66     //出栈操作
67     int Pop(SqStack *S, int *e);
68 #ifdef _cplusplus
69 }
70 #endif
71 #endif
  1 //CreateGraphDemo.c
  2 #include "CreateGraphDemo.h"
  3 int visited[20];
  4 //返回指定顶点在顶点向量中的位置
  5 int LocateVex(MGraph G, VertexType elem)
  6 {
  7     int i;
  8     for (i = 0; i < G.vexnum; ++i)
  9     if (strcmp(elem, G.vexs[i]) == 0)
 10         return i;
 11     return error;
 12 }
 13 void FloydMethods(int Dis [][MAX_VERTEX_NUM], int Path [][MAX_VERTEX_NUM], int _nVertexCount)
 14 {
 15     int i, j, k;
 16     // 先初始化Path
 17     for (i = 0; i < _nVertexCount; ++i)
 18     {
 19         for (j = 0; j < _nVertexCount; ++j)
 20         {
 21             Path[i][j] = i;
 22         }
 23     }
 24     for (k = 0; k < _nVertexCount; ++k)
 25     {
 26         for (i = 0; i < _nVertexCount; ++i)
 27         {
 28             for (j = 0; j < _nVertexCount; ++j)
 29             {
 30                 if ((Dis[i][k] + Dis[k][j]) < Dis[i][j])
 31                 {
 32                     // 找到更短路径
 33                     Dis[i][j] = Dis[i][k] + Dis[k][j];
 34                     Path[i][j] = Path[k][j];
 35                 }
 36             }
 37         }
 38     }
 39 }
 40 void ShowShortPath(int Dis [][MAX_VERTEX_NUM], int Path [][MAX_VERTEX_NUM], SqStack *S, MGraph *G)
 41 {
 42     int i, j, e, t, m, len = 0;
 43     char Name1[10], Name2[10];
 44     printf("\n请输入你想查找的两个景点名称 (两景点间用空格隔开) :  ");
 45     scanf("%s %s", Name1, Name2);
 46     printf("起源 -> 目的地   最小距离        最短路径\n");
 47     for (i = 0; i < G->vexnum; ++i)
 48     {
 49         for (j = 0; j < G->vexnum; ++j)
 50         {
 51             if (!strcmp(Name1, (*G).vexs[i]) && !strcmp(Name2, (*G).vexs[j]))
 52             {
 53                 printf("%s -> %s\t", (*G).vexs[i], (*G).vexs[j]);
 54                 if (1000 == Dis[i][j])    // i -> j 不存在路径
 55                 {
 56                     printf("%s-->>%s is no road\n", (*G).vexs[i], (*G).vexs[j]);;
 57                 }
 58                 else
 59                 {
 60                     printf("     %d\t\t", Dis[i][j]);
 61                     int k = j;
 62                     do
 63                     {
 64                         k = Path[i][k];
 65                         Push(S, k);
 66                         len++;
 67                     } while (k != i);
 68                     Pop(S, &e);
 69                     printf("%s", (*G).vexs[e]);
 70                     t = e;
 71                     for (m = 0; m < len; m++)
 72                     {
 73                         Pop(S, &e);
 74                         if (t != e)
 75                         {
 76                             printf(" -> %s", (*G).vexs[e]);
 77                         }
 78                         t = e;
 79                     }
 80                     printf(" -> %s\n", (*G).vexs[j]);
 81                 }
 82             }
 83         }
 84     }
 85 }
 86 int InitStack(SqStack *S)
 87 {
 88     S->base = (int *) malloc(50 * sizeof(int));
 89     if (!S->base)
 90         return error;
 91     S->top = S->base;
 92     returntrue;
 93 }
 94 int Push(SqStack *S, int e)
 95 {
 96     *(S->top++) = e;
 97     returntrue;
 98 }
 99 int Pop(SqStack *S, int *e)
100 {
101     if (S->top == S->base)
102         returnfalse;
103     *e = *(--(S->top));
104     returntrue;
105 }
106 //无向网
107 int CreateUDN(MGraph *G)
108 {
109     int i, j, k, l, IncInfo, w;//IncInfo表示弧是否有其他信息
110     char s[MAX_INFO], *info;
111     char va[10], vb[10];
112     printf("请输入校园中的景点个数,所有景点之间的马路条数,景点是否含有其他信息(是:1,否:0)");
113     scanf("%d,%d,%d", &(*G).vexnum, &(*G).arcnum, &IncInfo);
114     printf("请输入每个景点的名称(<%d个字符):\n", MAX_NAME);
115     for (i = 0; i < (*G).vexnum; ++i)//构造顶点向量
116     {
117         (*G).vexs[i] = (VertexType) malloc(sizeof(char) *MAX_NAME);
118         scanf("%s", (*G).vexs[i]);
119         getchar();
120     }
121     for (i = 0; i < (*G).vexnum; ++i)//初始化邻接矩阵
122     {
123         for (j = 0; j < (*G).vexnum; ++j)
124         {
125             (*G).arcs[i][j].adj = 1000;
126             (*G).arcs[i][j].info = NULL;
127         }
128     }
129     printf("请输入%d条路中每条路所连接的两个景点(以空格隔开): \n", (*G).arcnum);
130     for (k = 0; k < (*G).arcnum; ++k)
131     {
132         scanf("%s %s", va, vb);//输入弧头,弧尾信息
133         printf("请输入该条路的长度 : ");
134         scanf("%d", &w);
135         i = LocateVex(*G, va);//定位弧尾位置,
136         j = LocateVex(*G, vb);//定位弧头位置
137         (*G).arcs[i][j].adj = w;//权值大小
138         (*G).arcs[j][i].adj = w;
139         if (IncInfo)
140         {
141             printf("请输入该景点的相关信息(<%d个字符) : ", MAX_INFO);
142             scanf("%s", s);
143             l = strlen(s);
144             if (l)
145             {
146                 (*G).arcs[i][j].info = (char *) malloc((l + 1)*sizeof(char));
147                 strcpy((*G).arcs[i][j].info, s);
148             }
149         }
150     }
151     (*G).kind = DN;
152     returntrue;
153 }
154 //有向网
155 int CreateDN(MGraph *G)
156 {
157     int i, j, k, l, IncInfo, w;//IncInfo表示弧是否有其他信息
158     char s[MAX_INFO], *info;
159     char va[5], vb[5];
160     printf("请输入校园中的景点个数,所有景点之间的马路条数,景点是否含有其他信息(是:1,否:0)");
161     scanf("%d,%d,%d", &(*G).vexnum, &(*G).arcnum, &IncInfo);
162     printf("请输入每个景点的名称(<%d个字符)\n", MAX_NAME);
163     for (i = 0; i < (*G).vexnum; ++i)//构造顶点向量
164     {
165         (*G).vexs[i] = (VertexType) malloc(sizeof(char) * 5);
166         scanf("%s", (*G).vexs[i]);
167         getchar();
168     }
169     for (i = 0; i < (*G).vexnum; ++i)//初始化邻接矩阵
170     for (j = 0; j < (*G).vexnum; ++j)
171     {
172         (*G).arcs[i][j].adj = 1000;
173         (*G).arcs[i][j].info = NULL;
174     }
175     printf("请输入%d条路中每条路所连接的两个景点(以空格隔开): \n", (*G).arcnum);
176     for (k = 0; k < (*G).arcnum; ++k)
177     {
178         scanf("%s %s", va, vb);//输入弧头,弧尾信息
179         printf("请输入该条路的长度 : ");
180         scanf("%d", &w);
181         i = LocateVex(*G, va);//定位弧尾位置,
182         j = LocateVex(*G, vb);//定位弧头位置
183         (*G).arcs[i][j].adj = w;//权值大小
184         if (IncInfo)
185         {
186             printf("请输入该景点的相关信息(<%d个字符) : ", MAX_INFO);
187             scanf("%s", s);
188             l = strlen(s);
189             if (l)
190             {
191                 (*G).arcs[i][j].info = (char *) malloc((l + 1)*sizeof(char));
192                 strcpy((*G).arcs[i][j].info, s);
193             }
194         }
195     }
196     (*G).kind = DN;
197     returntrue;
198 }
199 int Display(MGraph *G)
200 {
201     int i, j;
202     printf("邻接矩阵输出 :\n");
203     for (i = 0; i < G->vexnum; i++)
204     {
205         for (j = 0; j < G->vexnum; j++)
206         {
207             printf("%d  ", G->arcs[i][j].adj);
208         }
209         printf("\n");
210     }
211 }
212 int DisplayVexs(MGraph *G)
213 {
214     int i;
215     printf("---------------------景点:--------------------\n");
216     for (i = 0; i < G->vexnum; ++i)
217     {
218         printf("%s   ", G->vexs[i]);
219     }
220     printf("\n------------------------------------------------\n\n");
221 }
222 int FreeGraph(MGraph **G)
223 {
224     int i, j;
225     for (i = 0; i < (*(*G)).vexnum; i++)
226     {
227         free((*G)->vexs[i]);
228         (*G)->vexs[i] = NULL;
229         for (j = 0; j < (*(*G)).vexnum; j++)
230         {
231             if ((*G)->arcs[i][j].info)
232             {
233                 free((*G)->arcs[i][j].info);
234                 (*G)->arcs[i][j].info = NULL;
235             }
236         }
237     }
238     free(*G);
239     *G = NULL;
240     returntrue;
241 }
 1 //main.c
 2 #include "CreateGraphDemo.h"
 3 int main(int argc, char *argv [])
 4 {
 5     int i, j, a[20][20], b[20][20];
 6     char ch;
 7     SqStack S;
 8     MGraph **p, *G = (MGraph *) malloc(sizeof(MGraph));
 9     p = &G;
10     CreateUDN(G);
11     //CreateDN(G);
12     for (i = 0; i < G->vexnum; ++i)
13     {
14         for (j = 0; j < G->vexnum; ++j)
15         {
16             a[i][j] = G->arcs[i][j].adj;
17         }
18     }
19     InitStack(&S);
20     FloydMethods(a, b, G->vexnum);
21 loop:
22     DisplayVexs(G);
23     ShowShortPath(a, b, &S, G);
24     printf("Again ? (Y/N)\n");
25     getchar();
26     scanf("%c", &ch);
27     if (‘y‘ == ch || ‘Y‘ == ch)
28         goto loop;
29     FreeGraph(p);
30     return 0;
31 }

这是我之前写的一个校园导航的Demo,希望对大家有用……

本文出自 “驿落黄昏” 博客,请务必保留此出处http://yiluohuanghun.blog.51cto.com/3407300/879900

“Chaos”的算法之Floyd算法,布布扣,bubuko.com

时间: 2024-10-21 09:23:51

“Chaos”的算法之Floyd算法的相关文章

hihoCoder - 1089 - 最短路径&#183;二:Floyd算法 (floyd算法!!)

#1089 : 最短路径·二:Floyd算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 万圣节的中午,小Hi和小Ho在吃过中饭之后,来到了一个新的鬼屋! 鬼屋中一共有N个地点,分别编号为1..N,这N个地点之间互相有一些道路连通,两个地点之间可能有多条道路连通,但是并不存在一条两端都是同一个地点的道路. 由于没有肚子的压迫,小Hi和小Ho决定好好的逛一逛这个鬼屋,逛着逛着,小Hi产生了这样的问题:鬼屋中任意两个地点之间的最短路径是多少呢? 提示:其实如果你开心

最短路径算法之一——Floyd算法

Floyd算法 Floyd算法可以用来解决任意两个顶点之间的最短路径问题. 核心公式为: Edge[i][j]=Min{Edge[i][j],Edge[i][k]+Edge[k][j]}. 即通过对i,j两个顶点之间插入顶点后比较路径的大小来进行松弛. 首先我们来定义一个二维数组Edge[MAXN][MAXN]来存储图的信息. 这个图的Edge数组初始化以后为 相当于任意两点之间不允许经过其他点时的距离情况. Code1: 1 //经过1号顶点 2 for(i=1;i<=n;i++) 3 for

所有顶点之间的最短路径算法:Floyd算法。

Floyd算法的基本思想是:设集合S的初始状态为空,然后依次向集合S中加入顶点 0,1,...,n-1,每次加入一个顶点,用二维数组d保存各条最短路径的长度,其中d[i][j]存放的是顶点i到顶点j的最短路径的长度. 详细的说明: Floyd算法中最重要的办法为二维数组d[i][j],d[i][j]为从i到j中间只经过S中的顶点的.所有可能的路径中的最短路径的长度.如果从i到j通过S中的节点无法联通,则设置d[i][j]为正无穷.可以称d[i][j]存放的是从i到j的 当前最短路径 的长度.而随

Dijkstra算法,Floyd算法以及A*算法

Dijkstra算法 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. Floyd算法 Floyd算法是一个经典的动态规划算法.用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径.从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在) 从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点

最短路径-Dijkstra算法与Floyd算法

一.最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1    ADE:2   ADCE:3   ABCE:3 ②在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径. AE:100   ADE:90   ADCE:60   ABCE:70 ③单源点最短路径问题 问题描述:给定带权有向图G=(V, E)和源点v∈V,求从v到G中其余各顶点的最短路径. 应用实例--计算机网络传输的问题:怎样找到一种最经济的方式,从一台计算机向网上所有其它计算机发送一条消息. ④每

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法 本篇名言:"希望是厄运的忠实的姐妹. --普希金" 我们继续来看下数据结构图中的一个算法,这个算法来自图灵奖得主. 1.  Floyd算法介绍 Floyd算法又称为插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名.注意这个可不是心理学的那个弗洛伊德. 是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径

hiho一下 第二十四周---最短路径&#183;二:Floyd算法

最短路径·二:Floyd算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 万圣节的中午,小Hi和小Ho在吃过中饭之后,来到了一个新的鬼屋! 鬼屋中一共有N个地点,分别编号为1..N,这N个地点之间互相有一些道路连通,两个地点之间可能有多条道路连通,但是并不存在一条两端都是同一个地点的道路. 由于没有肚子的压迫,小Hi和小Ho决定好好的逛一逛这个鬼屋,逛着逛着,小Hi产生了这样的问题:鬼屋中任意两个地点之间的最短路径是多少呢? 提示:其实如果你开心的话,完全可以从

Floyd算法的原理和实现

一.算法介绍 Floyd算法是一种在有向图中求最短路径的算法.相比不能再有向图中包含负权值的dijkstra算法,Floyd算法可以用在拥有负权值的有向图中求解最短路径(不过不能包含负权回路).它是一种求解有向图中点与点之间最短路径的算法. 我们检查有向图中的每一个节点X,对于图中过的2点A和B,如果有Dis(AX)+Dis(XB)<Dis(AB),那么使得Dis(AB)=Dis(AX)+Dis(XB).当所有的节点X遍历完后,AB的最短路径就求出来了. 所以,核心代码很简单,其中N是顶点个数,

图论之最短路01——最短路矩阵(FLOYD)算法

%======================================================== %最短路矩阵算法,FLOYD算法 %针对性:方案预算,能求出所有点之间的最短路(最小费用等) %======================================================== function D=zuiduanjulijuzhen(quanzhijuzhen) n=length(quanzhijuzhen); D=quanzhijuzhen; m