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

求最短路径的经典方法有很多种,最常用的便是迪杰斯特拉算法和佛洛依德(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的最短路径的距离。

直接上代码:

 /* 求各个顶点对之间的最短路径 */
for (int k = ; k < G.vtxCnt; ++k) { // 顶点循环
for (int i = ; i < G.vtxCnt; ++i) { // 起点循环
for (int j = ; j < G.vtxCnt; ++j) { // 终点循环
// 判断是否存在更短的路径,有,则边值矩阵和路径矩阵更新;dist[in][post]得出的是in到post的最短路径
if (dist[i][j] > dist[i][k] + dist[k][j]) {
dist[i][j] > dist[i][k] + dist[k][j];
path[i][j] = path[k][j];
}
}
}
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)。

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

 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是顶点关系类型,对无权图,用1或0表示相邻否,对带权图,则为权值类型
InfoType *info;//该弧相关信息的指针
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct
{
VertexType vexs[MAX_VERTEX_NUM]; // 顶点向量
AdjMatrix arcs; // 邻接矩阵
VRType vexnum, arcnum; // 图的当前顶点数和弧数
GraphKind kind; // 图的种类标志
}MGraph;
//栈的结构
typedefstruct
{
VRType *base;
VRType *top;
}SqStack;
#ifdef __cplusplus
extern"C"{
#endif
//返回指定顶点elem在顶点向量中的位置
int LocateVex(MGraph G, VertexType elem);
//创建无向网
int CreateUDN(MGraph *G);
//创建有向图
int CreateDN(MGraph *G);
//显示其对应的邻接矩阵
int Display(MGraph *G);
//显示景点
int DisplayVexs(MGraph *G);
//释放空间
int FreeGraph(MGraph **G);
//最短路径算法
void FloydMethods(int Dis [][MAX_VERTEX_NUM], int Path [][MAX_VERTEX_NUM], int vexnum);
//输出最短路径以及路径长度
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[];
//返回指定顶点在顶点向量中的位置
int LocateVex(MGraph G, VertexType elem)
{
int i;
for (i = ; i < G.vexnum; ++i)
if (strcmp(elem, G.vexs[i]) == )
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 = ; i < _nVertexCount; ++i)
{
for (j = ; j < _nVertexCount; ++j)
{
Path[i][j] = i;
}
}
for (k = ; k < _nVertexCount; ++k)
{
for (i = ; i < _nVertexCount; ++i)
{
for (j = ; 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 = ;
char Name1[], Name2[];
printf("\n请输入你想查找的两个景点名称 (两景点间用空格隔开) : ");
scanf("%s %s", Name1, Name2);
printf("起源 -> 目的地 最小距离 最短路径\n");
for (i = ; i < G->vexnum; ++i)
{
for (j = ; 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 ( == 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 = ; 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( * 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;
}
//无向网
int CreateUDN(MGraph *G)
{
int i, j, k, l, IncInfo, w;//IncInfo表示弧是否有其他信息
char s[MAX_INFO], *info;
char va[], vb[];
printf("请输入校园中的景点个数,所有景点之间的马路条数,景点是否含有其他信息(是:1,否:0)");
scanf("%d,%d,%d", &(*G).vexnum, &(*G).arcnum, &IncInfo);
printf("请输入每个景点的名称(<%d个字符):\n", MAX_NAME);
for (i = ; i < (*G).vexnum; ++i)//构造顶点向量
{
(*G).vexs[i] = (VertexType) malloc(sizeof(char) *MAX_NAME);
scanf("%s", (*G).vexs[i]);
getchar();
}
for (i = ; i < (*G).vexnum; ++i)//初始化邻接矩阵
{
for (j = ; j < (*G).vexnum; ++j)
{
(*G).arcs[i][j].adj = ;
(*G).arcs[i][j].info = NULL;
}
}
printf("请输入%d条路中每条路所连接的两个景点(以空格隔开): \n", (*G).arcnum);
for (k = ; k < (*G).arcnum; ++k)
{
scanf("%s %s", va, vb);//输入弧头,弧尾信息
printf("请输入该条路的长度 : ");
scanf("%d", &w);
i = LocateVex(*G, va);//定位弧尾位置,
j = LocateVex(*G, vb);//定位弧头位置
(*G).arcs[i][j].adj = w;//权值大小
(*G).arcs[j][i].adj = w;
if (IncInfo)
{
printf("请输入该景点的相关信息(<%d个字符) : ", MAX_INFO);
scanf("%s", s);
l = strlen(s);
if (l)
{
(*G).arcs[i][j].info = (char *) malloc((l + )*sizeof(char));
strcpy((*G).arcs[i][j].info, s);
}
}
}
(*G).kind = DN;
returntrue;
}
//有向网
int CreateDN(MGraph *G)
{
int i, j, k, l, IncInfo, w;//IncInfo表示弧是否有其他信息
char s[MAX_INFO], *info;
char va[], vb[];
printf("请输入校园中的景点个数,所有景点之间的马路条数,景点是否含有其他信息(是:1,否:0)");
scanf("%d,%d,%d", &(*G).vexnum, &(*G).arcnum, &IncInfo);
printf("请输入每个景点的名称(<%d个字符)\n", MAX_NAME);
for (i = ; i < (*G).vexnum; ++i)//构造顶点向量
{
(*G).vexs[i] = (VertexType) malloc(sizeof(char) * );
scanf("%s", (*G).vexs[i]);
getchar();
}
for (i = ; i < (*G).vexnum; ++i)//初始化邻接矩阵
for (j = ; j < (*G).vexnum; ++j)
{
(*G).arcs[i][j].adj = ;
(*G).arcs[i][j].info = NULL;
}
printf("请输入%d条路中每条路所连接的两个景点(以空格隔开): \n", (*G).arcnum);
for (k = ; k < (*G).arcnum; ++k)
{
scanf("%s %s", va, vb);//输入弧头,弧尾信息
printf("请输入该条路的长度 : ");
scanf("%d", &w);
i = LocateVex(*G, va);//定位弧尾位置,
j = LocateVex(*G, vb);//定位弧头位置
(*G).arcs[i][j].adj = w;//权值大小
if (IncInfo)
{
printf("请输入该景点的相关信息(<%d个字符) : ", MAX_INFO);
scanf("%s", s);
l = strlen(s);
if (l)
{
(*G).arcs[i][j].info = (char *) malloc((l + )*sizeof(char));
strcpy((*G).arcs[i][j].info, s);
}
}
}
(*G).kind = DN;
returntrue;
}
int Display(MGraph *G)
{
int i, j;
printf("邻接矩阵输出 :\n");
for (i = ; i < G->vexnum; i++)
{
for (j = ; j < G->vexnum; j++)
{
printf("%d ", G->arcs[i][j].adj);
}
printf("\n");
}
}
int DisplayVexs(MGraph *G)
{
int i;
printf("---------------------景点:--------------------\n");
for (i = ; i < G->vexnum; ++i)
{
printf("%s ", G->vexs[i]);
}
printf("\n------------------------------------------------\n\n");
}
int FreeGraph(MGraph **G)
{
int i, j;
for (i = ; i < (*(*G)).vexnum; i++)
{
free((*G)->vexs[i]);
(*G)->vexs[i] = NULL;
for (j = ; 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[][], b[][];
char ch;
SqStack S;
MGraph **p, *G = (MGraph *) malloc(sizeof(MGraph));
p = &G;
CreateUDN(G);
//CreateDN(G);
for (i = ; i < G->vexnum; ++i)
{
for (j = ; 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 ;
}

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

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

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

  1. C++编程练习(11)----“图的最短路径问题“(Dijkstra算法、Floyd算法)

    1.Dijkstra算法 求一个顶点到其它所有顶点的最短路径,是一种按路径长度递增的次序产生最短路径的算法. 算法思想: 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的 ...

  2. 最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)

    一.主要内容: 介绍图论中两大经典问题:最小生成树问题以及最短路径问题,以及给出解决每个问题的两种不同算法. 其中最小生成树问题可参考以下题目: 题目1012:畅通工程 http://ac.jobdu ...

  3. Dijkstra 算法、Kruskal 算法、Prim算法、floyd算法

    1.dijkstra算法 算最短路径的,算法解决的是有向图中单个源点到其他顶点的最短路径问题. 初始化n*n的数组. 2.kruskal算法 算最小生成树的,按权值加入 3.Prim算法 类似dijk ...

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

    Floyd算法 Floyd算法可以用来解决任意两个顶点之间的最短路径问题. 核心公式为: Edge[i][j]=Min{Edge[i][j],Edge[i][k]+Edge[k][j]}. 即通过对i ...

  5. 最短路径算法——Dijkstra算法与Floyd算法

    转自:https://www.cnblogs.com/smile233/p/8303673.html 最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1    ADE:2  ...

  6. 弗洛伊德算法(Floyd算法)

    原博来自http://www.cnblogs.com/skywang12345/ 弗洛伊德算法介绍 和Dijkstra算法一样,弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的 ...

  7. 图论——最短路径 Dijkstra算法、Floyd算法

    1.弗洛伊德算法(Floyd) 弗洛伊算法核心就是三重循环,M [ j ] [ k ] 表示从 j 到 k 的路径,而 i 表示当前 j 到 k 可以借助的点:红色部分表示,如果 j 到 i ,i 到 ...

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

    一.最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1    ADE:2   ADCE:3   ABCE:3 ②在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径 ...

  9. 最短路径 Dijkstra算法 AND Floyd算法

    无权单源最短路:直接广搜 void Unweighted ( vertex s) { queue <int> Q; Q.push( S ); while( !Q.empty() ) { V ...

随机推荐

  1. nginx 内置变量大全(转)

    HTTP核心模块支持一些内置变量,变量名与apache里的对应.比如 $http_user_agent,$http_cookie等表示HTTP请求信息的变量.更多变量:$args, 请求中的参数; $ ...

  2. Spring依赖注入构造器注入(通过构造函数注入)

    在src目录下建立applicationContext.xml   (Spring 管理 bean的配置文件) <?xml version="1.0" encoding=&q ...

  3. Java学习笔记----main

    1.java中main方法是程序的入口方法.main还是必须的两个修饰符是public和static.举例 A:public static void main(String args[]) B:pub ...

  4. php四种排序算法实现代码

    分享php排序的四种算法与代码. 冒泡:function bubble_sort($arr){ $num = count($arr); for($i=0;$i<$num;$i++){ for($ ...

  5. TreeView 高速单击时不运行AfterCheck时间

    解决方法1: 在AfterCheck事件中,通过System.Threading.Thread.Sleep()来控制函数的运行的最短时间.保证函数运行时间必须大于某个值 解决方法2: 编写列TreeV ...

  6. 五、String在Java中是传“引用”

    这个是Java的经典问题.许多类似的问题在stackoverflow被提问,有很多不正确或不完备的答案.如果不想太多你会认为这个问题比较简单.( The question is simple if y ...

  7. JAVA-JSP指令元素之page指令

    相关资料:<21天学通Java Web开发> 结果总结:1.page设定JSP页面全局属性,作用于整个JSP页面,包括静态包含的文件2.<%@ page 属性1="属性值1 ...

  8. 基于jquery右侧悬浮加入购物车代码

    分享一款基于jquery右侧悬浮加入购物车代码.这是一款基于jQuery实现的仿天猫右侧悬浮加入购物车菜单代码. 在线预览   源码下载 实现的代码: <!--左侧产品parabola.js控制 ...

  9. Curved UI - VR Ready Solution To Bend Warp Your Canvas 1.7,1.8,2.2,2.3 四种版本压缩包(Unity UGUI曲面插件),可以兼容VRTK

    Curved UI - VR Ready Solution To Bend Warp Your Canvas 1.7,1.8,2.2,2.3 四种版本压缩包(Unity UGUI曲面插件) 可以兼容V ...

  10. LAN8710A/LAN8710Ai datasheet 记录

    因为产品的双网口出现了问题,而且是AM335x 内部驱动,难度比较大,现从PHY 端开始分析相关原理,找到双网口不能使用的原因. 此篇是记录一些有关LAN8710A 这个PHY的一些特性. 各个功能模 ...