“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的最短路径的距离。
直接上代码:
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];
}
}
}
}
那么接下来的问题就是,我们如何找出最短路径呢?这里需要借助一个辅助数组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[20];
//返回指定顶点在顶点向量中的位置
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请输入你想查找的两个景点名称 (两景点间用空格隔开) : ");
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;
}
//无向网
int CreateUDN(MGraph *G)
{
int i, j, k, l, IncInfo, w;//IncInfo表示弧是否有其他信息
char s[MAX_INFO], *info;
char va[10], vb[10];
printf("请输入校园中的景点个数,所有景点之间的马路条数,景点是否含有其他信息(是:1,否:0)");
scanf("%d,%d,%d", &(*G).vexnum, &(*G).arcnum, &IncInfo);
printf("请输入每个景点的名称(<%d个字符):\n", MAX_NAME);
for(i = 0; i < (*G).vexnum; ++i)//构造顶点向量
{
(*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("请输入%d条路中每条路所连接的两个景点(以空格隔开): \n", (*G).arcnum);
for(k = 0; 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+1)*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[5], vb[5];
printf("请输入校园中的景点个数,所有景点之间的马路条数,景点是否含有其他信息(是:1,否:0)");
scanf("%d,%d,%d", &(*G).vexnum, &(*G).arcnum, &IncInfo);
printf("请输入每个景点的名称(<%d个字符)\n", MAX_NAME);
for(i = 0; i < (*G).vexnum; ++i)//构造顶点向量
{
(*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("请输入%d条路中每条路所连接的两个景点(以空格隔开): \n", (*G).arcnum);
for(k = 0; 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+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("---------------------景点:--------------------\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;
}
这是我之前写的一个校园导航的Demo,希望对大家有用……
“chaos”的算法--之Floyd算法详解(求最短路径)相关推荐
- 详解BFS,Dijkstra算法,Floyd算法是如何解决最短路径问题的
目录 1.BFS算法 2.Dijkstra算法 3.Floyd算法 4.总结 1.BFS算法 G纲是个物流离散中心,经常需要往各个城市运东西,怎么运送距离最近--单源最短路径问题 各个城市之间也学要来 ...
- 操作系统:基于页面置换算法的缓存原理详解(下)
概述: 在上一篇<操作系统:基于页面置换算法的缓存原理详解(上)>中,我们主要阐述了FIFO.LRU和Clock页面置换算法.接着上一篇说到的,本文也有三个核心算法要讲解.分别是LFU(L ...
- 希尔排序基础java代码_java 算法之希尔排序详解及实现代码
摘要:这篇Java开发技术栏目下的"java 算法之希尔排序详解及实现代码",介绍的技术点是"希尔排序详解.实现代码.希尔排序.Java.实现.代码",希望对大 ...
- kmeans python interation flag_机器学习经典算法-logistic回归代码详解
一.算法简要 我们希望有这么一种函数:接受输入然后预测出类别,这样用于分类.这里,用到了数学中的sigmoid函数,sigmoid函数的具体表达式和函数图象如下: 可以较为清楚的看到,当输入的x小于0 ...
- python实验原理_Python实现蒙特卡洛算法小实验过程详解
蒙特卡洛算法思想 蒙特卡洛(Monte Carlo)法是一类随机算法的统称,提出者是大名鼎鼎的数学家冯·诺伊曼,他在20世纪40年代中期用驰名世界的赌城-摩纳哥的蒙特卡洛来命名这种方法. 通俗的解释一 ...
- Matlab中的FCM算法代码及中文详解
Matlab中的FCM算法代码及中文详解 转自:http://xiaozu.renren.com/xiaozu/106512/336681453 function [center, U, obj_fc ...
- 图解机器学习算法(6) | 决策树模型详解(机器学习通关指南·完结)
作者:韩信子@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/34 本文地址:https://www.showmeai.tech/article-d ...
- KMP算法之next数组详解
KMP算法之next数组详解 KMP算法实现原理 KMP算法是一种非常高效的字符串匹配算法,下面我们来讲解一下KMP算如何高效的实现字符串匹配.我们假设如下主串和模式串: int i;//i表示主串的 ...
- 天津理工大学《操作系统》实验二,存储器的分配与回收算法实现,代码详解,保姆式注释讲解
天津理工大学<操作系统>实验二,存储器的分配与回收算法实现,代码详解,保姆式注释讲解 实验内容 1. 本实验是模拟操作系统的主存分配,运用可变分区的存储管理算法设计主存分配和回收程序,并不 ...
最新文章
- 设置 HTTP HEADER 字段来提高 Web 安全性
- azure java_Azure File服务(5): Java开发
- Python-Day3-数据类型
- linux中的file命令
- 三值的排序 Sorting a Three-Valued Sequence
- 汉语编程能获得诺贝尔奖
- SAP ABAP RFC table administration
- Android相对布局(RelativeLayout)常用属性、练习使用按键、文本框等控件、线性布局(LinearLayout)属性
- baseapp01: [S_ERROR]: [Account 40 => dbid 196]---------->call server client2base_xz Generate an err
- 米斯特白帽培训讲义 漏洞篇 SQL 注入
- python utc时间如何取整_Python和Pandas:如何在不同的分辨率上取整unix时间戳(utc):1min5min15min30min1d?...
- 使用tornado让你的请求异步非阻塞
- wireshark: You don‘t have permission to capture on that device
- Dynamics CRM2013/2015 禁止欢迎屏幕(Disable the Welcome Screen)
- 003 python 注释/数据类型/运算符/输入输出/格式化输出
- 分配系统盘容量应考虑三要素
- npm发布vue组件库
- 数学中的圆周率符号怎么输入
- .then()方法是异步执行
- 读书笔记:少有人走的路
热门文章
- mysql 导入txt数据到数据表【原创】
- 想拥有一款钢铁侠Jarvis管家的软件吗?
- ssl初一组周六模拟赛【2018.3.31】
- MySql数据库学习--存储过程(1)
- java Io流实现图片复制
- Hadoop 部署实例
- 用户强烈反对产品改动,如何应对?
- 原阿里中供梁法锋:O2O产品的地推管理 | SHARE 2015产品经理O2O论坛实录
- Exchange 退信550 5.1.11 RESOLVER.ADR.ExRecipNotFound
- find_in_set()和in()比较