数据结构中的Floyd算法和Dijkstra算法是求最短路径的经典算法,但是由于数据结构的学习只能学习其中算法核心,但是实际的上机实践以及算法实现能力却很不足,因此借此准备机试之机,将自己近期的学习心得写下,作为笔记
(由于Floyd算法思路清晰,代码实现简单,复杂度为n3,先通过此算法学习)
Floyd(弗洛伊德)算法:是求所有顶点到各顶点的最短路径的问题,算法的核心在与每次都选择一个顶点,作为中间节点c,如果a->b的路径距离大于a->c->b的路径距离,则更新a->b的最短距离,所以此算法是要经过三层循环遍历,用一个二维数组作为邻接矩阵。时间复杂度高,但是代码实现简单。
注:当程序的示例范围在100个顶点以内时,可以采用Floyd算法,并且不会超时,以下是算法的核心代码
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++){
if(a[i][k]==n||a[k][j]==n)
//当前中间节点不通
continue;
if(a[i][k]+a[k][j]<a[i][j])
a[i][j]=a[i][k]+a[k][j];//更新最短路径
}
}
}
Dijkstra(迪杰斯特拉)算法:是求单源点到所有顶点的最短路径的算法,该算法是利用贪心策略,每次选择与当前顶点距离最短的另一个顶点,只要这个顶点未被选择过(设置一个标记数组mark[ ]),则计算通过这个顶点作为中间节点的路径是否比原先的距离短,如果短,则更新,否则不更新。还要将该顶点对应的位置标记数组置为true。
该算法要用的结构体、邻接链表、标记数组等
核心代码如下
Dis[1]=0; mark[1]=true;//先添加节点1
int newp=1;
for(int i=1;i<n;i++)//n-1次循环
{
for(int j=0;j<edge[newp].size();j++)
{
int t = edge[newp][j].next;//保存其邻接节点
int cost = edge[newp][j].c; //保存路径长度
if(mark[t]==true) continue;
if(Dis[t]==-1||Dis[t]>Dis[newp]+cost) //更新
Dis[t] = Dis[newp] + cost;
}
}
#include<iostream>
#include<cstdio>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<vector>
#include<stdlib.h>
#include<algorithm> //排序函数的头文件
using namespace std;
struct E{
int next;
int c;
};
vector <E> edge[505];//邻接链表
int Dis[505];
bool mark[505]; //标记数组
int main(){
int n,m;
int a,b,c;
while(cin>>n>>m){
for(int i=1;i<=n;i++)
{
edge[i].clear();//初始化
Dis[i]=-1;
mark[i] = false;
}
while(m--){
cin>>a>>b>>c;//表示从a到b有一条权值为c的路径
E tmp;
tmp.c = c;
tmp.next = b;
edge[a].push_back(tmp);//把b加入a的邻接链表中
tmp.next = a;
edge[b].push_back(tmp); //把a加入到b的邻接链表中
}
Dis[1]=0; mark[1]=true;//先添加节点1
int newp=1;
for(int i=1;i<n;i++)//n-1次循环
{
for(int j=0;j<edge[newp].size();j++)
{
int t = edge[newp][j].next;//保存其邻接节点
int cost = edge[newp][j].c;
if(mark[t]==true) continue;
if(Dis[t]==-1||Dis[t]>Dis[newp]+cost) //更新
Dis[t] = Dis[newp] + cost;
}
}
int Min = 10000;
for(int j=1;j<=n;j++) //选择最小的一个顶点输出
{
if(mark[j]==true) continue;
if(Dis[j]==-1) continue;
if(Dis[j]<Min){
Min = Dis[j];
newp = j;//起点更新
}
}
mark[newp]= true;
for(int i=1;i<=n;i++)
cout<<Dis[i]<<" "<<;
cout<<endl;
}
}