Dijkstra和Floyd求最短路径

记录一下这两个算法

Dijkstra

#include<stdlib.h>
#include<stdio.h>
#include<iostream>
using namespace std;
/*邻接矩阵法*/
#define MAXV 50
#define INF 32767

typedef struct 
{
    int edges[MAXV][MAXV];
    int n,e;
}MatGraph;
void CreateGraph(MatGraph &G)//创建的是带权有向图
{
    int n,e;
    int x,y,w;
    printf("输入顶点和边的个数:\n");
    cin>>n>>e;
    G.e=e;G.n=n;
    for(int i=0;i<G.n;i++)
    for(int j=0;j<G.n;j++)
    {
        if(i==j)
        G.edges[i][j]=0;
        else
        G.edges[i][j]=INF;
    }
    for(int i=0;i<G.e;i++)
    {
        printf("输入第%d条边的信息\n",i+1);
        cin>>x>>y>>w;
        G.edges[x][y]=w;
    }
}
void Dispath(MatGraph g,int dist[],int path[],int S[],int v)
{//输出从v出发的所有最短路径
    int i,j,k;
    int apath[MAXV],d;
    for(i=0;i<g.n;i++)
        if(S[i]==1&&i!=v)
        {
            printf("从顶点%d到顶点%d的路径长度为:%d\t路径为:",v,i,dist[i]);
            d=0;apath[d]=i;
            k=path[i];
            if(k==-1)
            printf("没有路\n");
            else
            {
                while(k!=v)
                {
                    d++;apath[d]=k;
                    k=path[k];
                }
                d++;apath[d]=v;
                for(j=d;j>=0;j--)
                printf("%d\t",apath[j]);
                printf("\n");
            }  
        }

}
void Dijkstra(MatGraph g,int v)
{
    int dist[MAXV],path[MAXV];
    int S[MAXV];
    int MINDIS,i,j,u;
    for(i=0;i<g.n;i++)//初始化
    {
        dist[i]=g.edges[v][i];
        S[i]=0;
        if(g.edges[v][i]<INF)
        path[i]=v;//顶点v到i有边的话,置i的前一个顶点为v
        else
        path[i]=-1;//没有边
    }
    S[v]=1;path[v]=0;//v放入集合S中
    for(i=0;i<g.n-1;i++)//循环直到所有顶点的最短路径求出
    {
        MINDIS=INF;
        for(j=0;j<g.n;j++)
        {
            if(S[j]==0&&dist[j]<MINDIS)//选取不在S中且具有最短路径的顶点u
            {
                u=j;
                MINDIS=dist[j];
            }
        }
        S[u]=1;
        for(j=0;j<g.n;j++)
        if(S[j]==0)
            if(g.edges[u][j]<INF&&dist[u]+g.edges[u][j]<dist[j])
            {//如果v u j 的路径比 v j 路径短
                dist[j]=dist[u]+g.edges[u][j];
                path[j]=u;
            }
    }
    Dispath(g,dist,path,S,v);
}

int main()
{
    MatGraph G;
    CreateGraph(G);
    printf("输入起点v:\n");
    int n;scanf("%d",&n);
    Dijkstra(G,n);
}

Floyd

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
#define MAXV 50
#define INF 32767

typedef struct 
{
    int edges[MAXV][MAXV];
    int n,e;
}MatGraph;
void CreateGraph(MatGraph &G)//创建的是带权有向图
{
    int n,e;
    int x,y,w;
    printf("输入顶点和边的个数:\n");
    cin>>n>>e;
    G.e=e;G.n=n;
    for(int i=0;i<G.n;i++)
    for(int j=0;j<G.n;j++)
    {
        if(i==j)
        G.edges[i][j]=0;
        else
        G.edges[i][j]=INF;
    }
    for(int i=0;i<G.e;i++)
    {
        printf("输入第%d条边的信息\n",i+1);
        cin>>x>>y>>w;
        G.edges[x][y]=w;
    }
}
void Dispath(int n,int A[][MAXV],int path[][MAXV])
{
    int i,j,k,s;
    int apath[MAXV],d;
    for(i=0;i<n;i++)
    for(j=0;j<n;j++)
    {
        if(A[i][j]!=INF&&i!=j)//i->j有路径
        {
            printf("从%d到%d的路径为:",i,j);
            k=path[i][j];
            d=0;apath[d]=j;//终点
            while(k!=-1&&k!=i)
            {
                d++;apath[d]=k;
                k=path[i][k];
            }
            d++;apath[d]=i;//起点
            for(s=d;s>=0;s--)
            printf("%d\t",apath[s]);
            printf("路径长度为%d\n",A[i][j]);
        }
    }
}
void floyd(MatGraph G)
{
    int A[MAXV][MAXV],path[MAXV][MAXV];//迭代用的数组
    int i,j,k;
    //初始化
    for(i=0;i<G.n;i++)
    for(j=0;j<G.n;j++)
    {
        A[i][j]=G.edges[i][j];
        if(i!=j&&G.edges[i][j]<INF)//i->j有边
            path[i][j]=i;
        else
            path[i][j]=-1;
    }
    //考察所有顶点
    for(k=0;k<G.n;k++)
    for(i=0;i<G.n;i++)
    for(j=0;j<G.n;j++)
    {
        if(A[i][j]>A[i][k]+A[k][j])
        {
            A[i][j]=A[i][k]+A[k][j];
            path[i][j]=path[k][j];
        }
    }
    int n=G.n;
    Dispath(n,A,path);
}

int main()
{
    MatGraph G;
    CreateGraph(G);
    floyd(G);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值