复试机试之Floyd算法&Dijkstra算法的实现

数据结构中的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;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值