图算法

This commit is contained in:
yinkanglong_lab
2021-03-13 22:59:23 +08:00
parent fbd2a369b3
commit e67d805774
5 changed files with 69 additions and 60 deletions

View File

@@ -14,16 +14,19 @@
## 1 问题分析
最短路径算法。用于计算一个节点到其他节点的最短路径。
* 最短路径算法。用于**计算一个节点到其他节点的最短路径。**
Dijkstra算法算是贪心思想实现的首先把起点到所有点的距离存下来找个最短的然后松弛一次再找出最短的所谓的松弛操作就是遍历一遍看通过刚刚找到的距离最短的点作为中转站会不会更近如果更近了就更新距离这样把所有的点找遍之后就存下了起点到其他所有点的最短距离。
* Dijkstra算法算是**贪心思想**实现的,首先把起点到所有点的距离存下来找个最短的,然后松弛一次再找出最短的,所谓的松弛操作就是,遍历一遍看通过刚刚找到的距离最短的点作为中转站会不会更近,如果更近了就更新距离,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离。
## 2 算法原理
通过Dijkstra计算图G中的最短路径时需要指定起点s(即从顶点s开始计算)。
* 通过Dijkstra计算图G中的最短路径时需要指定起点s(即从顶点s开始计算)。
此外引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度)而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
* 此外引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度)而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
初始时S中只有起点sU中是除s之外的顶点并且U中顶点的路径是"起点s到该顶点的路径"。然后从U中找出路径最短的顶点并将其加入到S中接着更新U中的顶点和顶点对应的路径。 然后再从U中找出路径最短的顶点并将其加入到S中接着更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。
* 初始时S中只有起点sU中是除s之外的顶点并且U中顶点的路径是"起点s到该顶点的路径"。
* 然后从U中找出路径最短的顶点并将其加入到S中
* 接着更新U中的顶点和顶点对应的路径。
* 然后再从U中找出路径最短的顶点并将其加入到S中接着更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。
## 3 算法步骤
@@ -103,10 +106,10 @@ MGraph::MGraph(int n,int e){
vertexNum=n;
arcNum=e;
for(int i=0;i<vertexNum;i++)
vertex[i]=i;
vertex[i]=i;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
arc[i][j]=10000;
for(int j=0;j<n;j++)
arc[i][j]=10000;
cout<<"请输入图中各边的情况:"<<endl;
for(int k=0;k<e;k++){
cin>>i>>j;
@@ -118,41 +121,41 @@ void Dijkstra(MGraph G,int v){
string path[Max];
for(int i=0;i<G.vertexNum;i++)
{
dist[i]=G.arc[v][i];
if(dist[i]!=10000)
path[i]=Int_to_String(G.vertex[v])+"->"+Int_to_String(G.vertex[i]);
else
path[i]="";
dist[i]=G.arc[v][i];
if(dist[i]!=10000)
path[i]=Int_to_String(G.vertex[v])+"->"+Int_to_String(G.vertex[i]);
else
path[i]="";
}
s[0]=v;
dist[v]=0;
int num=1;
for(int i=0;i<G.vertexNum;i++)
{
int t=10000,k;
for(int j=0;j<G.vertexNum;j++)
{
if(dist[j]<t&&dist[j]!=0)
int t=10000,k;
for(int j=0;j<G.vertexNum;j++)
{
t=dist[j];
k=j;
if(dist[j]<t&&dist[j]!=0)
{
t=dist[j];
k=j;
}
}
}
cout<<"终点为:"<<k<<" 最短路径长度为:"<<dist[k]<<" 过程:"<<path[k]<<endl;
s[num++]=k;
for(int j=0;j<G.vertexNum;j++){
if(dist[j]!=0&&dist[j]>(dist[k]+G.arc[k][j])){
dist[j]=dist[k]+G.arc[k][j];
path[j]=path[k]+"->"+Int_to_String(j);
cout<<"终点为:"<<k<<" 最短路径长度为:"<<dist[k]<<" 过程:"<<path[k]<<endl;
s[num++]=k;
for(int j=0;j<G.vertexNum;j++){
if(dist[j]!=0&&dist[j]>(dist[k]+G.arc[k][j])){
dist[j]=dist[k]+G.arc[k][j];
path[j]=path[k]+"->"+Int_to_String(j);
}
}
}
dist[k]=0;
if(num==G.vertexNum)
break;
dist[k]=0;
if(num==G.vertexNum)
break;
}
cout<<"找到终点的顺序为:"<<endl;
for(int i=1;i<num;i++)
cout<<s[i]<<" ";
cout<<s[i]<<" ";
cout<<endl;
}
int main(){

View File

@@ -13,44 +13,33 @@
> * [https://blog.csdn.net/jeffleo/article/details/53349825](https://blog.csdn.net/jeffleo/article/details/53349825)
## 1 问题分析
Floyd算法是一个经典的**动态规划算法**它又被称为插点法。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。Floyd算法是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,算法目标是寻找从点i到点j的最短路径。
* Floyd算法是一个经典的**动态规划算法**它又被称为插点法。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。Floyd算法是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,算法目标是寻找从点i到点j的最短路径。
## 2 算法原理
Floyd算法的基本思想
可以将问题分解:
第一、先找出最短的距离
第二、然后在考虑如何找出对应的行进路线。
* Floyd算法的基本思想可以将问题分解:
* 第一、先找出最短的距离
* 第二、然后在考虑如何找出对应的行进路线。
> 以后再整理一下文字内容
如何找出最短路径呢这里还是用到动态规划的知识对于任何一个城市而言i到j的最短距离不外乎存在经过i与j之间经过k和不经过k两种可能所以可以令k=123...n(n是城市的数目)在检查d(ij)与d(ik)+d(kj)的值在此d(ik)与d(kj)分别是目前为止所知道的i到k与k到j的最短距离因此d(ik)+d(kj)就是i到j经过k的最短距离。所以若有d(ij)>d(ik)+d(kj)就表示从i出发经过k再到j的距离要比原来的i到j距离短自然把i到j的d(ij)重写为d(ik)+d(kj)每当一个k查完了d(ij)就是目前的i到j的最短距离。重复这一过程最后当查完所有的k时d(ij)里面存放的就是i到j之间的最短距离了。
接下来就要看一看如何找出最短路径所行经的城市了这里要用到另一个矩阵P它的定义是这样的p(ij)的值如果为p就表示i到j的最短行经为i->...->p->j也就是说p是i到j的最短行径中的j之前的最后一个城市。P矩阵的初值为p(ij)=i。有了这个矩阵之后要找最短路径就轻而易举了。对于i到j而言找出p(ij)令为p就知道了路径i->...->p->j再去找p(ip)如果值为qi到p的最短路径为i->...->q->p再去找p(iq)如果值为ri到q的最短路径为i->...->r->q所以一再反复到了某个p(it)的值为i时就表示i到t的最短路径为i->t就会的到答案了i到j的最短行径为i->t->...->q->p->j。因为上述的算法是从终点到起点的顺序找出来的所以输出的时候要把它倒过来。
但是如何动态的回填P矩阵的值呢回想一下当d(ij)>d(ik)+d(kj)时就要让i到j的最短路径改为走i->...->k->...->j这一条路但是d(kj)的值是已知的换句话说就是k->...->j这条路是已知的所以k->...->j这条路上j的上一个城市(即p(kj))也是已知的当然因为要改走i->...->k->...->j这一条路j的上一个城市正好是p(kj)。所以一旦发现d(ij)>d(ik)+d(kj)就把p(kj)存入p(ij)。
## 3 算法过程
![](image/2021-03-13-22-44-58.png)
![](image/Floyd算法.png)
> 顶点名称和下标的对应
> * A B C D E F G
> * 0 1 2 3 4 5 6
1. 定义n×n的方阵序列D-1, D0 , … Dn1,
1. 弗洛伊德算法定义了两个二维矩阵
* 矩阵D记录顶点间的最小路径。例如D[0][3]= 10说明顶点0 到 3 的最短路径为10
* 矩阵P记录顶点间最小路径中的中转点
* 例如P[0][3]= 1 说明0 到 3的最短路径轨迹为0 -> 1 -> 3。
2. 初始化: D-1C
D-1[i][j]=边<i,j>的长度表示初始的从i到j的最短路径长度即它是从i到j的中间不经过其他中间点的最短路径。
2. 它通过3重循环k为中转点v为起点w为终点循环比较D[v][w] 和 D[v][k] + D[k][w] 最小值如果D[v][k] + D[k][w] 为更小值则把D[v][k] + D[k][w] 覆盖保存在D[v][w]中。
3. 迭代设Dk-1已求出如何得到Dk0≤k≤n-1
3. 以A为中间点原D矩阵中D[B][G]的值为INF即不存在B->G的最小路径但是通过A为中间点D[B][A] + D[A][G] = 12 + 14 = 26 小于 D[B][G] = INF 所以D[B][A] + D[A][G] 为 B -> G的最小值因此覆盖D[B][G] 为 26。
* Dk-1[i][j]表示从i到j的中间点不大于k-1的最路径pi…j
* 考虑将顶点k加入路径p得到顶点序列qi…k…j
* 若q不是路径则当前的最短路径仍是上一步结果Dk[i][j]= Dk1[i][j]
* 否则若q的长度小于p的长度则用q取代p作为从i到j的最短路径
4. 因为q的两条子路径i…k和k…j皆是中间点不大于k1的最短路径所以从i到j中间点不大于k的最短路径长度为
$$
Dk[i][j]min\{ Dk-1[i][j], Dk-1[i][k] +Dk-1[k][j]\}
$$
4. 以B为中间点第2步后的D矩阵中D[A][C]的值为INF 但是通过BD[A][B] + D[B][C] = 12 + 10 = 22 小于 D[A][C] = INF所以D[A][B] + D[B][C] 为 A->C的最路径,覆盖D[A][C]的值为22 以此类推。
## 4 算法效率
@@ -59,6 +48,23 @@ $$
## 5 算法实现
```
//这里是弗洛伊德算法的核心部分
//k为中间点
for(k = 0; k < G.vexnum; k++){
//v为起点
for(v = 0 ; v < G.vexnum; v++){
//w为终点
for(w =0; w < G.vexnum; w++){
if(D[v][w] > (D[v][k] + D[k][w])){
D[v][w] = D[v][k] + D[k][w];//更新最小路径
P[v][w] = P[v][k];//更新最小路径中间顶点
}
}
}
}
```
```C++
#include<iostream>
#include<string.h>
using namespace std;

View File

@@ -10,7 +10,7 @@
> 参考文献
> [https://www.cnblogs.com/ggzhangxiaochao/p/9070873.html](https://www.cnblogs.com/ggzhangxiaochao/p/9070873.html)
## 1 问题描述
Kruskal算法是一种用来寻找最小生成树的算法由Joseph Kruskal在1956年发表。用来解决同样问题的还有Prim算法和Boruvka算法等。三种算法都是贪婪算法的应用。和Boruvka算法不同的地方是Kruskal算法在图中存在相同权值的边时也有效。
* Kruskal算法是一种用来寻找最小生成树的算法由Joseph Kruskal在1956年发表。用来解决同样问题的还有Prim算法和Boruvka算法等。三种算法都是贪婪算法的应用。和Boruvka算法不同的地方是Kruskal算法在图中存在相同权值的边时也有效。
## 2 算法原理
@@ -50,7 +50,7 @@ Kruskal算法是一种用来寻找最小生成树的算法由Joseph Kruskal
## 5 算法实现
```
```C++
typedef struct
{
char vertex[VertexNum]; //顶点表

View File

@@ -115,7 +115,7 @@
## 5 算法实现
```
```C++
#include <stdio.h>
#include <stdlib.h>
#define VertexType int

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 KiB