最短路径---迪杰斯特拉算法

【最短路径-迪杰斯特拉算法】


本算法以无向网为例,存储方式采用邻接矩阵

1)将该网以邻接矩阵的方式存储,由于这里的示例采用无向图,因此它是一个对称阵

2)选取A点为起始点,求A点到其他各个顶点之间的最短路径

3)算法开始跟prim算法类似,先用一个min_weight[]数组存储与顶点i有边相连的权值,并在每一次循环中找出与顶点i有边相连的权值最小边的顶点,并用数组final_mark[]标记找到的这个顶点(final_mark[i]=1意味着这个顶点被加入最短路径中)

4)接下来算法开始与prim不同了。经过3)找到了权值最小边的顶点j之后,再遍历邻接矩阵中与顶点j有边相连的权值,判断这些顶点的最短路径是从A直接到这些顶点的路径,还是从A经过顶点i再到这些顶点的路径和。若是后者,则更新min_weight[]权值数组,并用path[]数组记录最短路径的路径下标。

5)大循环直到将每一个顶点都判定完结为止


本算法的测试用例如下图所示:


其中左图为无向网图,右图为构造的邻接矩阵。下面贴出代码:

/*********************************************************************
算法复杂度:O(n^2)  其中n由顶点数决定
Author:tmw
date:2017-10-21
********************************************************************************************/
#include <stdio.h>
#include <stdlib.h>

#define MAX_VERTEX 100
#define inf 65535  //用65535代表无穷大
/*************************建立无向图邻接矩阵**************************/
typedef struct Matrix_Graph
{
    char vertex[MAX_VERTEX];//存储顶点信息
    int edge[MAX_VERTEX][MAX_VERTEX];//存储边信息
    int vertex_number,edge_number;//存储图中的顶点数和边数
}Matrix_Graph;
void create_non_direction_matrix_Graph( Matrix_Graph *G )
{
    int i,j,w,k;
    printf("请输入顶点数和边数:\n");
    scanf("%d %d",&G->vertex_number,&G->edge_number);

    printf("请输入无向图顶点信息(如ABCD...):\n");
    char ch;
    while( ( ch = getchar() ) != '\n' );
    for( i = 0 ; i < G->vertex_number ; i++ )
        scanf("%c",&G->vertex[i]);

    //初始化边信息
    for( i = 0 ; i < G->vertex_number ; i++ )
        for( j = 0 ; j < G->vertex_number ; j++ )
        {
            if( i == j )
                G->edge[i][j] = 0;
            else
                G->edge[i][j] = inf;
        }

    printf("请输入无向图中相连的两个顶点下标值(Vi,Vj),以及权值---即边信息\n");
    for( k = 0 ; k < G->edge_number ; k++ )
    {
        scanf("%d %d %d",&i,&j,&w);
        G->edge[i][j] = w;
        G->edge[j][i] = G->edge[i][j];//由于是无向图,故是对称阵
    }
    //打印邻接矩阵
    printf("*************************构造的邻接矩阵如下**************************\n");
    for( i = 0 ; i < G->vertex_number ; i++ )
    {
        for( j = 0 ; j < G->vertex_number ; j++ )
            printf("%d\t",G->edge[i][j]);
        printf("\n");
    }
}

/*************************迪杰斯特拉算法**************************/
int min_weight[MAX_VERTEX];//记录各点最短路径权值和,最后需作为程序的返回数组
int path[MAX_VERTEX];//记录各点最短路径下标,最后需作为程序的返回数组
int final_mark[MAX_VERTEX];//final_mark[i]=1意味着顶点i已加入最短路径中
/****找到array数组中,顶点i到A的实际路径下标及对最短路径长度,返回这个累加值****/
int find_print( Matrix_Graph *G , int array[] , int f )
{
    int re_min_weight = min_weight[f];
    printf("%c<-",G->vertex[f]);
    while( array[f] != 0 )
    {
        f = array[f];
        printf("%c<-",G->vertex[f]);
    }
    printf("%c",G->vertex[0]);
    return re_min_weight;
}
void Dijkstra(Matrix_Graph *G , int first_index , int min_weight[] , int path[])//以A点作为算法起点
{
    int i,j,k,min;

    /************初始化**************/
    for( i = 0 ; i < G->vertex_number ; i++ )
    {
        min_weight[i] = G->edge[0][i]; //初始化min_weight[]权值数组为所有与A点有边相连的边的权值
        path[i] = 0;  //初始化全部顶点最短路径的路径下标为0
        final_mark[i] = 0;//全部顶点初始化为还未求的最短路径状态
    }

    /*******将第一个顶点A纳入最开始的最短路径相关数组的记录当中******/
    final_mark[0] = 1;//标记顶点A已纳入最短路径中
    path[0] = 0;//标记A的最短路径为A到A

    /***遍历除A顶点外的其他顶点,每循环一次找到A到顶点i的最短路径***/
    for( i = 1 ; i < G->vertex_number ; i++ )
    {
        min = inf;
        //类似prim算法的操作:从起始顶点出发,找到与此顶点有边相连的权值最小的顶点,并记录
        for( j = 0 ; j < G->vertex_number ; j++ )
        {
            if( !final_mark[j] && min_weight[j] < min )//找到了与该起始顶点有边相连的权值较小的点
            {
                k = j;//记录顶点下标
                min = min_weight[j];//更新参考比较值,在结束for循环后,真正的min就找到了并且追踪了下标
            }
        }
        final_mark[k] = 1;//标记找到的距当前顶点最近的点
        //从标记的顶点出发,修正当前路径及距离
        for( j = 0 ; j < G->vertex_number ; j++ )
        {
            if( !final_mark[j] && min+G->edge[k][j] < min_weight[j] )//若前距离小于从A点直接到该点的距离,则更新距离及路径
            {
                path[j] = k;//修改当前路径
                min_weight[j] = min+G->edge[k][j];//修改当前距离
            }
        }
    }
    /*****打印最短路径及路径长度******/
    printf("*****结果输出******\n");
    int ans;
    for( i = 0 ; i < G->vertex_number ; i++ )
    {
        printf("顶点A到顶点%c的最短路径为: ",G->vertex[i]);
        ans = find_print(G,path,i);
        printf("\t\t路径长度为:%d\n",ans);
    }
}

int main()
{
    Matrix_Graph *G;
    G = (Matrix_Graph*)malloc(sizeof(Matrix_Graph));
    create_non_direction_matrix_Graph(G);
    Dijkstra(G,0,min_weight,path);
    return 0;
}

代码执行结果如下:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值