最短路径算法

article/2025/8/25 5:40:47

1.最短路径算法分为单源最短路径算法多源最短路径算法

(a)单源最短路径算法,可以计算出从起点到任意一个起点的最短路径。

例如:Dijkstra算法 ,SPFA算法

(b)多源最短路径算法,可以计算出任意两点之间的最短路径。

例如:Floyd算法。

(c)负权边,就是指图中有边的权值为负数,此时Dijkstra算法失效(无法计算出最短路径),SPFA算法和Floyd算法仍然有效。

(d)负权回路,也叫负权环。所有最短路径算法全部失效,但是用SPFA算法可以检测出负权环,Dijkstra算法,Floyd算法无法检测出负权环。

2.Dijkstra算法和SPFA算法

(1)Dijkstra算法分三步:第一步选最小,第二步标记,第三步更新。

(2)SPFA算法,本质上是BFS算法,主要采用队列,其关键操作是出队和入队。

(a)出队:每次队首的父结点出队

(b)入队:初始时起点入队,之后孩子入队必须要满足两个条件:条件1--经过父结点能使该孩子到起点的距离更短,条件2--孩子未在队中

代码示例:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2500+10,maxm=6200+10;//边数和点数要开足够
const int INF=1<<30;//2的30次方
struct Edge
{int v;int w;int next;
}e[maxm*2];
int cnt;//边的编号
int head[maxn];
int n, m, s, t;inline void AddEdge(int u,int v,int w)
{cnt++;//边的编号增加1e[cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;
}//SPFA 最环0(nm)随机图实践性很好。
void SPFA()
{int inq[maxn],d[maxn];queue<int> q;memset(inq,0,sizeof(inq));for(int i=1;i<=n;i++){d[i]=INF;}d[s]=0;//设置起点距离为零q.push(s);//起点入队inq[s]=1;//标记起点已经入队while(!q.empty()){int u=q.front();//取出父结点//cout<<u<<endl;q.pop();//父亲出队inq[u]=0;//表示是否在队里边,0表示不在队里,1表示在队里for(int i=head[u];i>=0;i=e[i].next){int v=e[i].v,w=e[i].w;if(d[v]>d[u]+w)//如果经过父亲结点u到子结点v的路径长度,比原先v到起点的路径更短{d[v]=d[u]+w;if(!inq[v])//如果v不在队列里,就让v入队{q.push(v);//让v入队,v已入队inq[v]=1;//标记//cout<<v<<":"<<d[v]<<" ";}}}}printf("%d\n",d[t]);
}//Dijkstra 0(mlogn)
struct HeapNode
{
//小根堆,储存最小的int u;//结点编号int d;//表示结点到起点的最短路径长度bool operator<(const HeapNode& rhs) const{return d>rhs.d;//定义了堆的排序规则}
};void Dijstra()//使用优先队列算法优化的算法
{int d[maxn];//它存第i个点到终点的最短路径priority_queue<HeapNode> q;for(int i=1;i<=n;i++){d[i]=INF;//先初始化让所有点到起点的距离为无穷大}d[s]=0;//将起点到起点的距离为零q.push((HeapNode){s,d[s]});//找到dist最小的(强制类型转换)while(!q.empty()){HeapNode x=q.top();//取出队首父亲xq.pop();//父亲出队int u=x.u;//取出x点的结点编号if(x.d != d[u]){continue;//跳过本次循环}for(int i=head[u];i>=0;i=e[i].next){int v=e[i].v;//取出第i条边的终点int w=e[i].w;//取出第i条边的权值if(d[u]+w<d[v])//如果经过父亲结点u到子结点v的路径长度,比原先v到起点的路径更短{d[v]=d[u]+w;//更新孩子q.push((HeapNode){v,d[v]});//被更新的子结点入队}}}cout<<d[t];//输出从t点到起点最短路径的长度
}
int main()
{memset(head,-1,sizeof(head));//初始化链表头cin>>n>>m>>s>>t;//读取结点数,边数,起点,终点int u, v, w;//边的起点,终点,权值for(int i=1;i<=m;i++)//读取边并存成图{cin>>u>>v>>w;AddEdge(u,v,w);AddEdge(v,u,w);}//Dijstra();SPFA();return 0;
}
/*
6
9
1 4
1 2 1
1 6 2
2 3 4
2 6 4
3 4 2
3 6 1
4 5 3
4 6 3
5 6 5
*/

调试技巧:用队列的算法在调试时通常通过父亲和孩子来找问题,一定要验证输入的正确性,(通过输出来验证)

3.Floyd算法

(1)这个算法是最简单功能最强大的最短路径算法,但缺点是时间复杂度高。

(2)相比其他算法,此算法必须背过。

(3)此算法是插点法,即如果经过k点能使i点和j点的最短路径变短,那就经过k点。此算法使用枚举方法,依次插入一个点,更新任意两点之间的最短路径。即在任意两点之间插入1号点,看是否能够跟新其最短路径;在任意两点之间插入2号点,看是否能够跟新其最短路径;...在任意两点之间插入n号点,看是否能够跟新其最短路径。

(4)关键代码:

 (5)注意事项:中间点k必须为外层循环(不可以互换),起点i和终点j可以互换。

(6)示例代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
const int INF=10000;
int n;//点的数量
int m;//边的数量
int g[maxn][maxn];//二维数组存图,邻接矩阵存图,数组的初始值全部为0
int d[maxn][maxn];//存储任意两点的最短路径长度
void insertEdge(int from,int to,int w)//边的起点终点和权值
{g[from][to]=w;
}
void Floyd()
{for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(d[i][j]>d[i][k]+d[k][j]){d[i][j]=d[i][k]+d[k][j];}}}}
}
int main()
{cin>>n>>m;for(int i=1;i<=m;i++){int from,to,w;cin>>from>>to>>w;insertEdge(from,to,w);insertEdge(to,from,w);}//初始化d数组,若两点之间存有边初始化成权值大小,没有边则初始为无穷大for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(g[i][j]>0)//i到j之间有边{d[i][j]=g[i][j];}else{d[i][j]=INF;}if(i==j){d[i][j]=0;}}}Floyd();for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cout<<i<<"->"<<j<<":"<<d[i][j]<<endl;}}return 0;
}
/*
6
9
1 2 1
1 6 2
2 3 4
2 6 4
3 4 2
3 6 1
4 5 3
4 6 3
5 6 5
*/


http://chatgpt.dhexx.cn/article/O2gTxVXl.shtml

相关文章

哈夫曼树及其应用

1、哈夫曼树的基本概念 ---- 哈夫曼&#xff08;Huffman&#xff09;树又称作最优二叉树&#xff0c;它是n个带权叶子结点构成的所有二叉树中&#xff0c;带权路径长度最小的二叉树。 ---- “路径”就是从树中的一个结点到另一个结点之间的分支构成的部分&#xff0c;而分支…

哈夫曼树的C语言实现

什么是哈夫曼树 当用 n 个结点&#xff08;都做叶子结点且都有各自的权值&#xff09;试图构建一棵树时&#xff0c;如果构建的这棵树的带权路径长度最小&#xff0c;称这棵树为“最优二叉树”&#xff0c;有时也叫“赫夫曼树”或者“哈夫曼树”。 在构建哈弗曼树时&#xff0…

哈夫曼树的构建及编码

哈夫曼树的构建及编码 文章目录 哈夫曼树的构建及编码一、什么是哈夫曼树二、什么是哈夫曼编码三、怎么建哈夫曼树、求哈夫曼编码四、为什么哈夫曼编码能实现压缩 声明&#xff1a;关于文件压缩&#xff0c;不是本文的重点&#xff0c;本文只说明并讨论哈夫曼树的构建和编码&am…

如何构建一棵哈夫曼树

给一个数列{10,7,8,3,26,5,1},要求转成为一棵哈夫曼树。 分析思路以及图解&#xff1a; 第一步&#xff1a;将数列进行排序&#xff0c;按从小到大的顺序。最终结果为{1,3,5,7,8,10,26}&#xff0c;根据每个数值创建结点&#xff0c;组成结点数组 第二步&#xff1a;取出权值最…

哈夫曼树 (100分)哈夫曼树

4-1 哈夫曼树 (100分)哈夫曼树 第一行输入一个数n&#xff0c;表示叶结点的个数。 需要用这些叶结点生成哈夫曼树&#xff0c;根据哈夫曼树的概念&#xff0c;这些结点有权值&#xff0c;即weight&#xff0c;题目需要输出哈夫曼树的带权路径长度&#xff08;WPL&#xff09;。…

哈夫曼树的编码和解码

哈夫曼树的作用&#xff1a;在数据通信中&#xff0c;需要将传送的文字转换成二进制的字符串&#xff0c;用0&#xff0c;1码的不同排列来表示字符。例如&#xff0c;需传送的报文为“AFTER DATA EAR ARE ART AREA”&#xff0c;这里用到的字符集为“A&#xff0c;E&#xff0c…

哈夫曼树与哈夫曼编码

哈夫曼树 给定n个权值作为n个叶子结点&#xff0c;构造一棵二叉树&#xff0c;若带权路径长度达到最小&#xff0c;称这样的二叉树为最优二叉树&#xff0c;也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树&#xff0c;权值较大的结点离根较近。 树节点间的边…

【例题】哈夫曼树

【例1】由五个分别带权值为9&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;14的叶子结点构成的一棵哈夫曼树&#xff0c;该树的带权路径长度为_______________。 A、60 B、66 C、67 D、50 答案&#xff1a;C 解析&#xff1a; 关键点在于要学会如何构造哈夫曼树 已知有5…

哈夫曼树以及哈夫曼算法

目录 一、哈夫曼树的定义 二、哈夫曼树的特点 三、哈夫曼算法(构造哈夫曼树的方法) 四、哈夫曼树的构造过程 五、哈夫曼树构造算法的实现 一、哈夫曼树的定义 1、哈夫曼树:最优树即带权路径长度(WPL)最短的树 “带权路径长度最短”是在"度相同”的树中比较而得的结果…

哈夫曼树的绘制

数据结构之哈夫曼树绘制 本人还是一个年轻的程序猿(还是个学生)&#xff0c;请大家多多指教&#xff01; 哈夫曼树 已知权重绘制哈夫曼树 开始我的表演 Step 1. 已知权重&#xff1a;2&#xff0c;3&#xff0c;3&#xff0c;4&#xff0c;7&#xff0c;6 Step 2. 选取其中…

哈夫曼树 哈夫曼编码

哈夫曼树 哈夫曼树的定义&#xff1a;设二叉树具有 n 个带权值的叶节点&#xff0c;那么从根节点到各个叶节点的路径长度与相应叶节点权值的乘积的和&#xff0c;叫作二叉树的带权路径长度 WPL (Weighted Path Length)。具有最小带权路径长度的二叉树称为哈夫曼树 (Huffman Tr…

哈夫曼树(Huffman Tree)

定义 哈夫曼树又称最优二叉树&#xff0c;是一种带权路径长度最短的二叉树。所谓树的带权路径长度&#xff0c;就是树中所有的叶结点的权值乘上其到根结点的路径长度&#xff08;若根结点为0层&#xff0c;叶结点到根结点的路径长度为叶结点的层数&#xff09;。树的路径长度是…

哈夫曼树详解

一、哈夫曼树的介绍 Huffman Tree&#xff0c;中文名是哈夫曼树或霍夫曼树&#xff0c;它是最优二叉树。 定义&#xff1a;给定n个权值作为n个叶子结点&#xff0c;构造一棵二叉树&#xff0c;若树的带权路径长度达到最小&#xff0c;则这棵树被称为哈夫曼树。 这个定义里面涉…

哈夫曼树(Huffmantree)

1.基本概念 哈夫曼树又称为最优树&#xff0c;是一类带权路径长度最短的树。 一些概念的定义&#xff1a; &#xff08;1&#xff09;路径&#xff1a;树的两个结点之间的连线称为路径。 &#xff08;2&#xff09;路径长度&#xff1a;路径上的分支数目称作路径长度。若规定…

哈夫曼树详解及其应用(哈夫曼编码)

一&#xff0c;哈夫曼树的基本概念 路径&#xff1a;从树中一个结点到另一个结点之间的分支构成这两个结点间的路径 结点的路径长度&#xff1a;两结点之间路径上的分支数 树的路径长度&#xff1a;从树根到每一个结点的路径长度之和&#xff0e;记作&#xff1a;&#xff3…

哈夫曼树编码的实现+图解(含全部代码)

目录 哈夫曼树的基本概念 ------------哈夫曼树的构造方法 ------------------------哈夫曼编码 ------------------------------------全部代码 哈夫曼树的基本概念 哈夫曼树通常以二叉树的形式出现&#xff0c;所以也称最优二叉树&#xff0c;是一类带权路径长度最短的树…

哈夫曼树(C语言实现)

文章目录 哈夫曼树的基本概念哈夫曼树的构建构建思路代码实现 哈夫曼编码的生成编码生成思路代码实现 完整代码展示以及代码测试 哈夫曼树的基本概念 在认识哈夫曼树之前&#xff0c;你必须知道以下几个基本术语&#xff1a; 1、什么是路径&#xff1f; 在一棵树中&#xff0c…

打开VS2010提示:产品密钥框

打开VS2010提示&#xff1a;产品密钥框&#xff0c;如下图&#xff1a; …

VS 2017 产品密钥

个人分类&#xff1a; vs2010 Visual Studio 2017&#xff08;VS2017&#xff09; 企业版 Enterprise 注册码&#xff1a;NJVYC-BMHX2-G77MM-4XJMR-6Q8QF Visual Studio 2017&#xff08;VS2017&#xff09; 专业版 Professional 激活码key&#xff1a;KBJFW-NXHK6-W4WJM-CRM…

vs++2010学习版的注册密钥

6VPJ7-H3CXH-HBTPT-X4T74-3YVY7 欢迎使用Markdown编辑器 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章&#xff0c;了解一下Markdown的基本语法知识。 新的改变 我们对Markdown编辑器进行…