• 最短路径--dijkstra算法


    最短路径dijkstra算法
    1.问题解释:
    从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径,称为最短路径


    2.算法特点:

    迪科斯彻算法使用了广度优先搜索解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树。该算法常用于路由算法或者作为其他图算法的一个子模块。


    3。算法的思路

    Dijkstra算法采用的是一种贪心的策略,声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T,初始时,原点 s 的路径权重被赋为 0 (dis[s] = 0)。若对于顶点 s 存在能直接到达的边(s,m),则把dis[m]设为w(s, m),同时把所有其他(s不能直接到达的)顶点的路径长度设为无穷大。初始时,集合T只有顶点s。
    然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点加入到T中,OK,此时完成一个顶点,
    然后,我们需要看看新加入的顶点是否可以到达其他顶点并且看看通过该顶点到达其他点的路径长度是否比源点直接到达短,如果是,那么就替换这些顶点在dis中的值。
    然后,又从dis中找出最小值,重复上述动作,直到T中包含了图的所有顶点。

    4.要点
    ①建立邻接矩阵,表示出各个点间的关联性, 不相连的两个点距离设为无限大
    ②将邻接矩阵第一行作为dis[]数组,存放第一个个点到所有点的最短路径,通过“松弛”方法依次寻找
    ③建立result[]数组,以0 1方式记录已经确定下来的最短路径

    5.实现
    //最短路径问题,确定原点及终点,查找路径。

    // 采用邻接矩阵表示图
    // 简单起见,邻接矩阵(图中各结点间的距离权值)在main函数中直接输入了 
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAXVEX 9
    #define INFINITY 65535
    
    typedef int Patharc[MAXVEX];  //存放最短路径上的结点编号
    typedef int ShortPathTable[MAXVEX]; //各节点到源点的路径(经过中间结点)长度
    
    typedef struct {
        int numVertexes;
        int *vex;
        int arc[MAXVEX][MAXVEX];
    }MGraph;
    
    void ShortestPath_Dijkstra(MGraph *G,int v0,int vv,Patharc *P,ShortPathTable *D)
    {
        int v,w,k,min;        
        //v: 各个节点的标号
        //w: 权重,即两个节点间的长度
        //k: 已计算过的节点的标记
        //min: 
        
        int result[MAXVEX];
    
        int n=0;
    
        for(v=0;v<G->numVertexes;++v)
        {
            result[v]=0;        //8位数组初始赋0,存储最短路径的结果,各个元素为节点标号
            (*D)[v]=G->arc[v0][v];  //初始化,其余各节点到源点的距离
            (*P)[v]=-1;
        }
    
    //输出当前距离表
    printf("
    ");
    for(w=0;w<G->numVertexes;++w)
    {
    printf("%d  ",(*D)[w]);
    }
    printf("
    ");
            
        (*D)[v0]=0;
        result[v0]=1; //源点加入
        (*P)[n++]=v0;
    
        for(v=0;v<G->numVertexes;++v)
        {
            min=INFINITY;
            for(w=0;w<G->numVertexes;++w) //寻找未加入的所有结点中到源点距离最短的结点k
            {
                if(!result[w] && (*D)[w]<min)
                {
                    k=w;
                    min=(*D)[w];
                }
            }
            result[k]=1; //结点k加入
            (*P)[n++]=k;    //加入最短路径
    
            //判断是否到达终点
            if(k==vv)
                break;
    printf("min=%d,k=%d
    ",min,k);
    
    
            for(w=0;w<G->numVertexes;++w) //更新其余各节点到源点的距离的距离数组
            {
                //if(!result[w] && (min+G->arc[k][w]<(*D)[w])) //新节点w到源点的距离=k到源点的距离+k到w的距离
                if(!result[w])
                {
                    (*D)[w]=min+G->arc[k][w];
                    printf("arc[%d][%d]=%d  ",k,w,G->arc[k][w]);
                    //(*P)[w]=k;
                }
            }
    //输出当前距离表
    printf("
    ");
    for(w=0;w<G->numVertexes;++w)
    {
    printf("%d    ",(*D)[w]);
    }
    
        }
        //输出结果
        printf("
    ");
        for(v=0;v<G->numVertexes;++v)
        {
            printf("%d-->",(*P)[v]);
        }
    
        printf("
    ");
    }
    
    void main()  
    {  
        MGraph *my_g=(MGraph*)malloc(sizeof(MGraph));  
        int i,j;  
        int t=0;
    
        int v0=0;
        int vv=8;
    
        my_g->numVertexes=9;  
        my_g->vex=(int*)malloc(sizeof(char)*my_g->numVertexes);  
        if(!my_g->vex) return;  
        for(i=0;i<my_g->numVertexes;++i)  //一维数组(图中各结点)初始化{0,1,2,3,4,5,6,7,8}  
            my_g->vex[i]=i++;
    
        for(i=0;i<my_g->numVertexes;++i)  
            for(j=0;j<my_g->numVertexes;++j)  
                my_g->arc[i][j]=INFINITY;
    
        // 无向图的权值二维数组为对称矩阵
        my_g->arc[0][1]=1;  my_g->arc[0][2]=5;
        my_g->arc[1][2]=3;  my_g->arc[1][3]=7;  my_g->arc[1][4]=5;  
        my_g->arc[2][4]=1;  my_g->arc[2][5]=7;
        my_g->arc[3][4]=2;  my_g->arc[3][6]=3;
        my_g->arc[4][5]=3;  my_g->arc[4][6]=6;  my_g->arc[4][7]=9;
        my_g->arc[5][7]=5;
        my_g->arc[6][7]=2;  my_g->arc[6][8]=7;
        my_g->arc[7][8]=4;
        for(i=0;i<my_g->numVertexes;++i)  
            for(j=0;j<=i;++j)  
            {  
                if(i==j)  
                {  
                    my_g->arc[i][j]=0;  
                    continue;  
                }  
                my_g->arc[i][j]=my_g->arc[j][i];  
            }  
        for(i=0;i<my_g->numVertexes;++i)  //二维数组表示图中各结点间连接边的weight  
        {  
            for(j=0;j<my_g->numVertexes;++j)  
                printf("%5d  ",my_g->arc[i][j]);  
            printf("
    ");  
        }  
        printf("
    
    ");
    
    
        Patharc P;
        ShortPathTable D;
        ShortestPath_Dijkstra(my_g,v0,vv,&P,&D);
    
        //free(my_g->vex);
        //free(my_g->arc);
    }
  • 相关阅读:
    Trie树
    递归函数两种方式的区别
    揭开HTTPS的神秘面纱
    补码到底是个什么东西
    浮点数的运算精度丢失
    PHP的stdClass
    2019-10-24
    MySQL存储引擎
    代码整洁之道小结
    NFS4 挂载同主机多个目录
  • 原文地址:https://www.cnblogs.com/edver/p/12589868.html
Copyright © 2020-2023  润新知