dijkstra算法求最短路径

希望大家能看完prim算法后再来看这个算法,因为两者思路差不多。
先来看一下自定义的结构体

typedef char VexType;
typedef int AdjType;
typedef struct{
    int n;
    VexType vexs[MaxNode];//保存节点
    AdjType arcs[MaxNode][MaxNode];//从矩阵获得节点与节点间的距离
}GraphMatrix;
typedef struct{
    AdjType length;//边长
    int prevex;//先驱节点
}path;

主程序

void main()
{
    GraphMatrix *mygraph;
    path *mydist;
//  Edge *mymst;
    mygraph = (GraphMatrix*)malloc(sizeof(GraphMatrix));
    //mymst = (Edge*)malloc(sizeof(Edge));
    mydist = (path*)malloc(sizeof(path));
    CreateGraph(mygraph,6);
    printf("testing creategraph\n");
    dijkstra(mygraph,mydist);
    printf("testing dijkstra:\n");
    print_path(mygraph,mydist);

}

creategraph函数是从txt里读取矩阵的函数,我写在了prim算法的帖子里,大家可以去看一下,这里就不说了。
来看一下dikstra算法

void dijkstra(GraphMatrix *graph,path *dist)
{
    int i,j,min;
    AdjType minw;
    dist[0].length = 0;
    dist[0].prevex = 0;
    graph->arcs[0][0] = 1;//表示v0加入集合
    for(i=1;i<graph->n;i++)//从V1节点开始
    {
        dist[i].length = graph->arcs[0][i];//初始化v0到各个节点的距离
        if(dist[i].length!=Max)
        {
            dist[i].prevex = 0;//不等于Max说明V0可以到Vi节点
        }
        else
        {
            dist[i].prevex = -1;//V0到Vi没有路径
        }
    }
    for(i=1;i<graph->n;i++)//一次循环就会找到V0到其中一个顶点的最短距离,所以循环节点数-1次
    {
        minw = Max;
        min = 0;
        for(j=1;j<graph->n;j++)
        {
            if((graph->arcs[j][j]==0)&&(dist[j].length<minw))//==0说明节点j还未加入
            {
                minw = dist[j].length;
                min = j;
            }
        }
        if(min==0)//如果都不等于0,说明所有节点都已加入,也就是已经调整好了,如果都大于minw说明所有路径已经达到最短
        {
            break;
        }
        graph->arcs[min][min]=1;//将顶点为min的顶点加入集合,此时V0到Vmin的节点的最短距离已经找到,下面进行调整时就是判断通过Vmin点再到其他点距离是否会减少
        for(j=1;j<graph->n;j++)
        {
            if(graph->arcs[j][j]==1)
            {
                continue;//V0到节点Vi的最短路径已经找到,不在进行调整
            }
            if(dist[j].length>dist[min].length+graph->arcs[min][j])//V0到Vmin的距离+Vmin到Vj的距离
            {
                dist[j].length = dist[min].length+graph->arcs[min][j];//变更路径长度
                dist[j].prevex = min;//V0到Vj的先驱节点从V0变更成Vmin
            }
        }
    }
}

dist数组的元素是V0节点到其他各点的路径。如果二维数组的graph->arcs[i][i]的值为0,说明此时Vi节点还没加入我们的判断范围,就是说我们求得最短路径里不能经过Vi节点,所以我们一开始默认V0节点加入判断范围,也就是说,我们求得路径就是V0节点到其他节点的最短路径,所以for循环是从1开始的。以为不用求V0到V0的最短路径
先初始化V0到其他各节点的距离,这些距离是从txt里存储的矩阵中读取的。如果两个节点之间没有路径,就默认路径距离为1000.路径前驱节点为-1.
1.初始化完成后,进行fo循环来寻找最短路径。先找一条最短路径(当前数组元素里length最小的).if((graph->arcs[j][j]==0)&&(dist[j].length

void print_path(GraphMatrix* graph, path* dist)
{
    int i,j;
    for(i=1;i<graph->n;i++)
    {
        j = i;
        if(dist[i].length==Max)
        {
            printf("V0到V%d没有路径\n",i);//设定床为MAX说明没有路径
        }
        else
        {
            printf("V%d到V0的路径为:  %d ",i,i);
            while(dist[j].prevex!=0)//Vj的前驱节点不是V0说明经过其他节点Vx,V0到Vx的路径中的前驱节点为dist[j].prevex,循环验证
            {
                printf("%d ",dist[j].prevex);
                j = dist[j].prevex;
            }
            printf("0");
            printf("\nV%d到V0的路径长度为%d\n",i,dist[i].length);
            printf("\n\n");
        }
    }
}

这里其实就是把数组元素的一些成员打印出来。数组下标i就代表V0到Vi的最短路径.
需要说明两点.
1.上面已经提到了,如果路径长度等于MAX(1000)。说明两个节点之间没有路径。
2.我们找的最短路径是V0到其他节点的最短路径。如果第i条路径的前驱节点不是V0,假设为Vj,说明V0到这个节点的最短路径是经过其他节点的。这个时候我们还要找第J条路径,就这样往前找,知道前驱节点为V0.
最后看一下运行截图
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值