迪吉斯特算法-最短路径

迪吉斯特算法每次寻找最小权重

展示一下流程:

假设有向连通图是这一个,它有6个顶点分别是ABCDEF,8条路径

AF,AE,AC,BC,CD,DF,ED,EF:

256表示没连通,剩下的则是路径权重

 ABCDEF
A256(无穷)256(无穷)10256(无穷)30100
B256(无穷)256(无穷)5256(无穷)256(无穷)256(无穷)
C256(无穷)256(无穷)256(无穷)50256(无穷)256(无穷)
D256(无穷)256(无穷)256(无穷)256(无穷)256(无穷)10
E256(无穷)256(无穷)256(无穷)20256(无穷)60
F256(无穷)256(无穷)256(无穷)256(无穷)256(无穷)256(无穷)

1:初始化

my_final[0]=true;

D[]=开始点所在行的路径权重,也就是第一行//自己距离自己所以D[0]=0

my_final[]D[]
[0]:true0
[1]:false256(无穷)
[2]:false10
[3]:false256(无穷)
[4]:false30
[5]:false100

 

2.因为上图中D[2]最小,所以把AC并入,变成下表:

AC并入后,标记为已经由起点A到达C,所以final[2]=true;

并根据上面的邻接矩阵图寻找第三行,也就是顶点C与哪些顶点有相连

由图知道与D相连,发现D的下标3,final[3]等于false,并且由A经过C到D的路径长度10+50<256(无穷)

所以更改其值,如下表:

my_final[]D[]
true0
false256(无穷)
true10
false60
false30
false100

3.重复2的步骤,寻找表中最小且是false的;

上面的步骤可以找到最短路径长度,但是我们还需要知道是怎么走,路径最短的;

所以需要使用一个二维数组,帮我们记下

也就是程序中的Path  P;//注意P是一个二维数组的地址,bool类型

例如上面举的栗子:由A经过C到D

就记录P[3][j]=P[2][j]//注释:j是0到顶点数的所有值;

并且把P[3][3]=true;

更详细的注释在程序里面,剩下的就不罗嗦了

/*
迪吉斯特算法
最短路径
typedef int  数组
*/
#include <malloc.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define  MAX_LEN    20//图最大顶点数
#define  INFINITY   255
typedef  bool       Path[MAX_LEN][MAX_LEN];
typedef  int        short_table[MAX_LEN];//定义一个short_table类型
//short_table  D  ==>>   int D[MAX_LEN]
typedef  struct  graph
{
    int vexnum,arcnum;
    int tyust[MAX_LEN][MAX_LEN];
    char vex[MAX_LEN];
}*Graph;
void  DIJ_shortestpath(Graph G,int v0,Path P,short_table D)
{
    bool  my_final[MAX_LEN];
    int my_min;
    int v;
    //辅助数组final和D初始化
    for(int i=0;i<G->vexnum;i++)
    {
        my_final[i]=false;
        D[i]=G->tyust[v0][i];
        for(int w=0;w<G->vexnum;w++)
        {
            P[i][w]=false;//初值为0,没有路径
        }


        if(D[i]<INFINITY)
        {
            P[i][v0]=P[i][i]=true;//初始化传入顶点(0,也就是首列)那一列//把对角线置1,为了下面记录经过了哪些顶点
        }

    }

    D[v0]=0;
    my_final[v0]=true;

    for(int i=1;i<G->vexnum;i++)//剩余的顶点
    {
        my_min=INFINITY;
        for(int w=0;w<G->vexnum;w++)//寻找D中最小值
        {
            if(!my_final[w]&&D[w]<my_min)
            {
                my_min=D[w];
                v=w;
            }
        }
        my_final[v]=true;//标志已经到达
        //所有最小的加起来就是最小的
        for(int w=0;w<G->vexnum;w++)//新并入之后,替换
        {
            if(!my_final[w]&&my_min<INFINITY&&G->tyust[v][w]<INFINITY&&
               (my_min+G->tyust[v][w]<D[w]))//未标记,存在最小值,存在下一个连接点,连接点距离小于目前的距离//可以优化的
                {
                    D[w]=my_min+G->tyust[v][w];//替换成最小值
                    for(int j=0;j<G->vexnum;j++)
                    {
                        P[w][j]=P[v][j];//记录
                        P[w][w]=true;
                    }
                }
        }

    }
}

int get_pos(Graph my_map,char c)
{
    for(int i=0;i<my_map->vexnum;i++)
    {
        if(my_map->vex[i]==c)
        {
            return i;
        }
    }
    return -1;
}
void print(Graph my_map)
{
    for(int i=0;i<my_map->vexnum;i++)
    {
        for(int j=0;j<my_map->vexnum;j++)
        {
            printf("%-4d",my_map->tyust[i][j]);
        }
        cout<<endl;
    }
    cout<<endl;
}
Graph  creat_graph()//创建有向图
{
    char in1,in2;
    int vexnum,arcnum;
    int p1,p2,weiget;
    Graph  pit=(Graph)malloc(sizeof(graph));
    cout<<"请输入顶点数和边数"<<endl;
    cin>>vexnum>>arcnum;
    pit->arcnum=arcnum;
    pit->vexnum=vexnum;


    for(int i=0;i<vexnum;i++)
    {
        for(int j=0;j<vexnum;j++)
        {
            pit->tyust[i][j]=INFINITY;
        }
    }


    cout<<"请输入顶点:"<<endl;
    for(int i=0;i<vexnum;i++)
        cin>>pit->vex[i];


    for(int i=0;i<arcnum;i++)
    {
        cout<<"请输入边和权重"<<i+1<<endl;
        cin>>in1>>in2>>weiget;
        p1=get_pos(pit,in1);
        p2=get_pos(pit,in2);
        pit->tyust[p1][p2]=weiget;
    }
    print(pit);
    return pit;
}
void make_path(Graph g,bool *p,int k,int j)//路径寻找
{
    int start=k;//start等于开始点也就是0
    int MIN,MINNUM;
    while(start!=j)
    {
        MIN=INFINITY;
        for(int k=0;k<g->vexnum;k++)//寻找最小的,这是符合我们的先前记录的顺序的
        {
            if(g->tyust[start][k]<MIN&&p[k])
            {
                MIN=g->tyust[start][k];
                MINNUM=k;
            }
        }
        if(MIN==INFINITY)break;

        printf("%c",g->vex[MINNUM]);
        if(MINNUM!=j)//不是终点
        printf("->");
        p[MINNUM]=false;//标志
        start=MINNUM;
    }
    cout<<endl;
}
int main()
{
    int k=0;
    Path p;
    short_table d;
    Graph g=creat_graph();
    bool *path=(bool *)malloc(g->vexnum*sizeof(bool));
    DIJ_shortestpath(g,k,p,d);

    cout<<"最短路径数组p[][]:\n";
    for(int i=0;i<g->vexnum;i++)
    {
        for(int j=0;j<g->vexnum;j++)
        {
            cout<<p[i][j]<<" ";
        }
        cout<<endl;
    }
    cout<<endl;

    for(int i=0;i<g->vexnum;i++)
    {
        if(i!=k&&d[i]<INFINITY)//如果不是起点,并且最终有路径到达
        {
            printf("%c->%c:%d  ",g->vex[k],g->vex[i],d[i]);
            printf("%c->",g->vex[k]);
            for(int j=0;j<g->vexnum;j++)
            {
                path[j]=p[i][j];
            }
            make_path(g,path,k,i);//i是终点下标
        }
    }

    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值