算法分析与实践 作业2

1、问题

用Floyd算法求解下图各个顶点的最短距离。写出Floyd算法的伪代码和给出距离矩阵(顶点之间的最短距离矩阵),按实验报告模板编写算法。
在这里插入图片描述
对于下图使用Dijkstra算法求由顶点a到顶点h的最短路径,按实验报告模板编写算法。
在这里插入图片描述

2、解析

Floyd:
目的:找到最短路径
从任意节点i到任意节点j的最短路径只有两种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点i到节点j的最短路径的距离,对于每一个节点k,允许它作为中转点,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。
Dijkstra:
设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(visited表示,初始时visited中只有一个源点,以后每求得一条最短路径 , 就将加入到集合visited中,直到全部顶点都加入到visited中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入visited中。在加入的过程中,总保持从源点v到visited中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,visited中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括visited中的顶点为中间顶点的当前最短路径长度。

3、设计

Floyd:

#include<stdio.h>
#include<string.h>
const int inf= 0x3f3f3f3f;
const int maxn= 100 + 10;
int dis[maxn][maxn];
int n,m;   //n表示顶点数量,m表示边的数量

void floyd(){
    for(int k=1;k<=n;++k){
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j){
                if(dis[i][k]+dis[k][j]<dis[i][j])
                    dis[i][j]=dis[i][k]+dis[k][j];
            }
        }
    }
}
int main(){
    while(scanf("%d %d",&n,&m)!=EOF){
        memset(dis,inf,sizeof dis);      //初始化,令各个点之间的距离为无穷大
        for(int i=1;i<=m;++i){
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            dis[x][y]=z;                //有向图
        }
        for(int i=1;i<=n;++i)dis[i][i]=0;
        floyd();
        puts("距离矩阵:");			//输出距离矩阵
       	for(int i=0;i<=n;++i){
       		if(i!=0){
       			printf("%2d",i);
			   }
			   else{
			   	printf(" ");
			   }
		   } 
		   printf("\n");
        for(int i=1;i<=n;++i){          
            printf("%d:",i);
            for(int j=1;j<=n;++j){
                printf("%d%c",dis[i][j],j==n?'\n':' ');
            }
        }
    }
}

在这里插入图片描述
Dijkstra:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1010;
const int inf = 0x3f3f3f3f;
int mp[maxn][maxn];
int dis[maxn];
bool vis[maxn];
int n, m;                                             //n表示顶点数量,m表示边的数量

void dijkstra(int s) {                                //从s点出发,经过任意点
    memset(vis, false, sizeof(vis));
    memset(dis, inf, sizeof(dis));
    vis[s] = 1;                                       //判断该点是否被检查过
    for (int i = 1; i <= n; i++){
        dis[i] = mp[s][i];
    }
     dis[s] = 0;
    for (int time = 1; time <= n - 1; time++){         //共n个数,检查次数n-1次//
        int minn = inf;
        int p = 1;
        for (int i = 1; i <= n; i++){                 //贪心 找出局部最优解
            if (dis[i] < minn&&vis[i] != 1) {
                minn = dis[i];
                p = i;
            }
        }
        vis[p] = 1;                                   //判断该点是否被检查过
        for (int i = 1; i <= n; i++){                 //用p点优化所有点
            dis[i] = min(dis[i], dis[p] + mp[p][i]);  //比较
        }
    }
}

int main(){
    while(scanf("%d %d",&n,&m)!=EOF){
        memset(mp,inf,sizeof mp);         //初始化,令各个点之间的距离为无穷大
        for(int i=1;i<=m;++i){
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            mp[x][y]=z;                //有向图
        }
        dijkstra(1);
        printf("从1到n点的最短距离为:%d\n",dis[n]);
    }
}

在这里插入图片描述

4、分析

flyod算法复杂度:O(n^3)
dijkstra算法复杂度:O(n^2)

5、源码

flyod:https://github.com/zhaozhiliangzzl/-/blob/master/floyd
dijkstra:https://github.com/zhaozhiliangzzl/-/blob/master/dijkstra

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读