最短路算法:
- floyd算法
- Dijkstra算法
- Dijkstra算法(堆优化)
- ford算法
- spfa算法(ford算法的队列优化)
一、只有5行代码的floyd算法:
1、 什么是floyd算法
弗洛伊德算法是解决多元最短路径的算法(什么是多源, 顾名思义就是起点有多个, 跑完floyd算法就算出以每个顶点做起点到各个点的最短路径)。
2、时间复杂度 O(n^3), 空间复杂度O(n^2)
3、适用性:
1、多源最短路
2、带负权值的
优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单。
缺点:时间复杂度比较高,不适合计算大量数据。
4、代码实现
flody算法是从中间结点的角度来考虑的
for(k = 0;k < n;k++)
for(i = 0;i< n;i++)
for(j = 0;j <n;j++)
if(grap[i][k]!=inf&&grap[k][j]!=inf&&grap[i][j] > grap[i][k]+grap[k][j])
grap[i][j] = grap[i][k]+grap[k][j];
floyd算法用到的是动态规划算法。
动规公式: grap[i][j] = min(gtap[i][j], grap[i][k]+grap[k][j]).
对于floyd的证明:
二、单源最短路径的Dijkstra算法(未用堆排优化):
1、什么是Dijkstra
2、时间复杂度O(n^2):
为优化的时间复杂度:外循环n-1次, 内循环 2*n次 , 所以时间复杂度 O((n-1)(2*n))近似 O(n^2)
3、适用性:
1、单源最短路径
2、不带负权值的边
4、代码实现:
对于dijkstra我一般喜欢用邻接矩阵, 邻接表储存图
(1)实现代码1
/**********
原理
每次 通过 未使用的点中,距起点最近的那个点 去松弛其他点的距离 (其实就 用近点(从最近开始, 然后是第二近...) 松弛远的点, 本质就是贪心思想)
所以dijkstra 时间复杂度主要跟点的个数有关
***********/
#include<bits/stdc++.h>
#define inf 0x3f3f3f
using namespace std;
int G[1111][1111];// 邻接矩阵 , 也可以用邻接表
int n; //图中点的个数
void Dijkstra(int s, int d)// s 起点 , 终点
{
int i;
int dis[1111];// 存s到 其他各点的距离
/**初始化距离**/
for(i = 1;i <= n;i++) dis[i] = inf;// 到其他点的距离为无限大
dis[s] = 0; //初始化到自己为1
/***标记数组初始化****/
int book[1111];//标记数组,标记该点是否使用
memset(book, 0 , sizeof(book));//初始化 0表示未使用
for(i = 1;i <= n-1;i++)// 循环 n-1 次, 最远的那个点(就是距离 起点 第n近的点(这里第1近的点是起点自己)肯定不能松弛其他店)
{
/**********找点过程**********/
int u = -1;//-1 u表示未使用的点中,距起点最近的那个点,初始化z最近点的编号为 -1
int Min = inf;// 初始化 未使用的点中,距起点最近的那个点到起点的距离为 inf
for(int j = 1;j <= n;j++)
{
if(book[j] == 0&& dis[j] < Min)//寻找未使用的点中,距起点最近的那个顶点
{
Min = dis[j];
u