1.单源点的最短路径问题:给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径。

我们用一个例子来具体说明迪杰斯特拉算法的流程。

定义源点为 0,dist[i]为源点 0 到顶点 i 的最短路径。其过程描述如下:

步骤 dist[1] dist[2] dist[3] dist[4] 已找到的集合
第 1 步 8 1 2 +∞ {2}
第 2 步 8 × 2 4 {2, 3}
第 3 步 5 × × 4 {2, 3, 4}
第 4 步 5 × × × {2, 3, 4, 1}
第 5 步 × × × × {2, 3, 4, 1}

第 1 步:从源点 0 开始,找到与其邻接的点:1,2,3,更新dist[]数组,因 0 不与 4 邻接,故dist[4]为正无穷。在dist[]中找到最小值,其顶点为 2,即此时已找到 0 到 2 的最短路。

第 2 步:从 2 开始,继续更新dist[]数组:2 与 1 不邻接,不更新;2 与 3 邻接,因0→2→3dist[3]大,故不更新dist[3] ;2 与 4 邻接,因0→2→4dist[4]小,故更新dist[4]为 4。在dist[]中找到最小值,其顶点为 3,即此时又找到 0 到 3 的最短路。

第 3 步:从 3 开始,继续更新dist[]数组:3 与 1 邻接,因0→3→1dist[1]小,更新dist[1]为 5;3 与 4 邻接,因0→3→4dist[4]大,故不更新。在dist[]中找到最小值,其顶点为 4,即此时又找到 0 到 4 的最短路。

第 4 步:从 4 开始,继续更新dist[]数组:4 与 1 不邻接,不更新。在dist[]中找到最小值,其顶点为 1,即此时又找到 0 到 1 的最短路。

第 5 步:所有点都已找到,停止。

对于上述步骤,你可能存在以下的疑问:

若 A 作为源点,与其邻接的只有 B,C,D 三点,其dist[]最小时顶点为 C,即就可以确定A→C为 A 到 C 的最短路。但是我们存在疑问的是:是否还存在另一条路径使 A 到 C 的距离更小? 用反证法证明。

假设存在如上图的红色虚线路径,使A→D→C的距离更小,那么A→D作为A→D→C的子路径,其距离也比A→C小,这与前面所述 “dist[]最小时顶点为 C” 矛盾,故假设不成立。因此这个疑问不存在。

根据上面的证明,我们可以推断出,Dijkstra 每次循环都可以确定一个顶点的最短路径,故程序需要循环 n-1 次。

/*
迪杰斯特拉求单节点到其余各节点的最短路径。
visited数组用于保存顶点是否已经求过最短路径,pre数组用于保存最短路径的下标
dist数组用于保存初始节点到其余节点的最短路径长度。
该算法求有向图G的某顶点到其余节点的最短路径pre以及长度dist
pre[v]的值是v0-->...->v的路径中的前驱节点。D[v]表示v0-->...-->v的最短路径长度和。 可以证明迪杰斯特拉算法每次循环可以确定一个顶点的最短路径,所以主程序循环n-1次。
主程序循环主要做两件事:首先找出dist数组中的最小值,并记录下标,说明找到初始点到该下标的最短路径。
然后要比价初始点到该点的最短路径加上这点到其他初始点需要到的点的距离是否比初始点直接到这些点的距离短
如果要短,那么就更新dist数组,并且这些点的前驱节点就会变为v而不是开始的v0点。下一次主循环再去从dist中找
最小的值并且未求过的点,就是该点的最短路径。
*/
#include<iostream>
using namespace std;
int matrix[][];//邻接矩阵
bool visited[];//标记数组
int dist[];//原点到i顶点的最短距离
int pre[];//记录最短路径。pre[i]放的是i的前驱节点
int source;//源节点
int vertex_num;//顶点数
int edge_num;//边数 void Dijkstra(int source)
{
//首先初始化
memset(visited,,sizeof(visited));
visited[source] = true;
for (int i = ; i < vertex_num; i++)
{
dist[i] = matrix[source][i];
pre[i] = source;
} int min_cost;//最短距离
int min_cost_index;//权值最小的那个顶点的下标。(求好了)
//主循环
for (int i = ; i < vertex_num; i++)
{
min_cost = INT_MAX;
for (int j = ; j < vertex_num; j++)
{
//注意要确保这个点没有找过。
if (visited[j]==false&&dist[j] < min_cost)
{
min_cost_index = j;
min_cost = dist[j];
}
} visited[min_cost_index] = true;//找到某一个点的最短距离
//利用该点进行dist的更新,并且调整前驱。
for (int j = ; j < vertex_num; j++)
{
//确保有连接
if (visited[j] == false && matrix[min_cost_index][j] != INT_MAX&&min_cost+ matrix[min_cost_index][j] < dist[j])
{
dist[j] = min_cost + matrix[min_cost_index][j];
pre[j] = min_cost_index;
}
}
}
} int main()
{
cout << "请输入图的顶点数(<100):";
cin >> vertex_num;
cout << "请输出图的边数: ";
cin >> edge_num;
for (int i = ; i < vertex_num; i++)
{
for (int j = ; j < vertex_num; j++)
{
matrix[i][j] = (i != j) ? INT_MAX : ;
}
}
cout << "请输入边的信息:\n";
int u, v, w;
for (int i = ; i < edge_num; i++)
{
cin >> u >> v >> w;
matrix[u][v] = matrix[v][u] = w;
} cout << "请输入源点(<" << vertex_num << "): ";
cin >> source;
Dijkstra(source);
for (int i = ; i < vertex_num; i++)
{
if (i != source)
{
//路径是反的,从目标点向前不断找前驱的过程。
cout << source << "到" << i << "最短距离: " << dist[i] << ",路径是:" << i;
int t = pre[i];
while (t != source)
{
cout << "--" << t;
t = pre[t];
}
cout << "--" << source << endl;
}
}
return ;
}

2、弗洛伊德算法:

1)算法思想原理:

Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)

从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

2).算法描述:

a.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。   

b.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比己知的路径更短。如果是更新它。

3).Floyd算法过程矩阵的计算----十字交叉法

方法:两条线,从左上角开始计算一直到右下角 如下所示

给出矩阵,其中矩阵A是邻接矩阵,而矩阵Path记录u,v两点之间最短路径所必须经过的点

相应计算方法如下:

最后A3即为所求结果

typedef struct
{
char vertex[VertexNum]; //顶点表
int edges[VertexNum][VertexNum]; //邻接矩阵,可看做边表
int n,e; //图中当前的顶点数和边数
}MGraph; void Floyd(MGraph g)
{
  int A[MAXV][MAXV];
  int path[MAXV][MAXV];
  int i,j,k,n=g.n;
  for(i=;i<n;i++)
  for(j=;j<n;j++)
  {   
A[i][j]=g.edges[i][j];
   path[i][j]=-;
  }
  for(k=;k<n;k++)
  {
  for(i=;i<n;i++)
  for(j=;j<n;j++)
  if(A[i][j]>(A[i][k]+A[k][j]))
  {
  A[i][j]=A[i][k]+A[k][j];
  path[i][j]=k;
  }
 }
}

//代码来自于wsw_seu大佬

//仅仅是作为笔记,谢谢

最小路径算法(Dijkstra算法和Floyd算法)的更多相关文章

  1. 最短路径——Dijkstra算法和Floyd算法

    Dijkstra算法概述 Dijkstra算法是由荷兰计算机科学家狄克斯特拉(Dijkstra)于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图(无 ...

  2. 【转载】Dijkstra算法和Floyd算法的正确性证明

      说明: 本文仅提供关于两个算法的正确性的证明,不涉及对算法的过程描述和实现细节 本人算法菜鸟一枚,提供的证明仅是自己的思路,不保证正确,仅供参考,若有错误,欢迎拍砖指正   ----------- ...

  3. Dijkstra算法和Floyd算法的正确性证明

    说明: 本文仅提供关于两个算法的正确性的证明,不涉及对算法的过程描述和实现细节 本人算法菜鸟一枚,提供的证明仅是自己的思路,不保证正确,仅供参考,若有错误,欢迎拍砖指正   ------------- ...

  4. 最短路径Dijkstra算法和Floyd算法整理、

    转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijks ...

  5. 【转】最短路径——Dijkstra算法和Floyd算法

    [转]最短路径--Dijkstra算法和Floyd算法 标签(空格分隔): 算法 本文是转载,原文在:最短路径-Dijkstra算法和Floyd算法 注意:以下代码 只是描述思路,没有测试过!! Di ...

  6. 最短路径—Dijkstra算法和Floyd算法

    原文链接:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最后边附有我根据文中Dijkstra算法的描述使用jav ...

  7. 最短路径—大话Dijkstra算法和Floyd算法

    Dijkstra算法 算法描述 1)算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , ...

  8. 最短路径—Dijkstra算法和Floyd算法【转】

    本文来自博客园的文章:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html Dijkstra算法 1.定义概览 Dijk ...

  9. 【转载】最短路径—Dijkstra算法和Floyd算法

    注意:以下代码 只是描述思路,没有测试过!! Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始 ...

随机推荐

  1. 【Leetcode 做题学算法周刊】第二期

    首发于微信公众号<前端成长记>,写于 2019.11.05 背景 本文记录刷题过程中的整个思考过程,以供参考.主要内容涵盖: 题目分析设想 编写代码验证 查阅他人解法 思考总结 目录 20 ...

  2. MVC5用户控件

    1. 添加一个model,用于给用户控件传递数据: 2.添加一个部分视图 . 3. 部分视图中,引入model,用于传递数据 4. 在要插入用户控件的地方,这样写 @Html.Partial(&quo ...

  3. 基于node的前端组件包发布至nexus和npmjs

    目录 目录... 3 1. 前言... 1 2. 配置... 1 2.1. 建立组件的导出模块... 1 2.2. 建立组件入口文件... 1 2.3. 配置“ng-package.json”文件.. ...

  4. Django学习day6——模板

    在day4中,你可能已经注意到我们在例子视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python 代码之中. html = "<html><body& ...

  5. python爬虫-携程-eleven参数

    携程-eleven分析 一.eleven的位置 通过对旁边栈的分析,它是在另一个js文件中调用的.那个js文件是一个自调用的函数,所以我们可以直接copy下来,用浏览器执行看看 执行运行是会报错的,u ...

  6. 精心整理(含图版)|你要的全拿走!(R数据分析,可视化,生信实战)

    本文首发于“生信补给站”公众号,https://mp.weixin.qq.com/s/ZEjaxDifNATeV8fO4krOIQ更多关于R语言,ggplot2绘图,生信分析的内容,敬请关注小号. 为 ...

  7. 康托展开&逆康托展开学习笔记

    啊...好久没写了...可能是最后一篇学习笔记了吧 题目大意:给定序列求其在全排列中的排名&&给定排名求排列. 这就是康托展开&&逆康托展开要干的事了.下面依次介绍 一 ...

  8. go中的数据结构切片-slice

    1.部分基本类型 go中的类型与c的相似,常用类型有一个特例:byte类型,即字节类型,长度为,默认值是0: bytes = []btye{'h', 'e', 'l', 'l', 'o'} 变量byt ...

  9. 为什么我加了索引,SQL执行还是这么慢(二)?

    接上文 在MySQL中,有一些语句即使逻辑相同,执行起来的性能差异确实极大的. 还记得我们上文中的结论吗:如果想使用索引树搜索功能,就不能使用数据库函数来处理索引字段值,而是在不改变索引字段值的同时, ...

  10. python中的集合、元组和布尔

    #元组,元组跟列表一样,只不过列表可读可写,而元组一般用来只读,不修改#python中不允许修改元组的数据,也包括不能删除其中的元素. t1 = ('a','b','c','d','s','a') & ...