单源最短路径(堆优化的Dijkstra算法)

Dijkstra算法:设初始节点为v,起始节点到其他节点u的距离为图中v到u的直接线路的距离,如果v和u之间没有直接线路,则d[u]=INF(无穷大)。初始化S={v},寻找最短路径(即在d[]中寻找使d[u]最小的u),将u加入到S中,然后更改到u节点可到达节点的最小距离。再寻找次短路径,并将次短路径的目标节点(设为u)加入到S中,更改到u节点可到达节点的最小距离.如此下去,知道S=V.

一般的Dijkstra算法每次寻找最短路径的时间复杂度O(n),整个算法的时间复杂度为O(n^2).带堆优化的Dijkstra算法每次寻找最短路径时采用堆排序,时间复杂度O(logn)。整个算法的时间复杂度为O(n*logn).

#include<stdio.h>
#include<malloc.h>
#define INF 65535

typedef struct ArcNode{
    int dst;
    int value;
    struct ArcNode *nextarc;
}ArcNode;

typedef struct VNode{
    int data;
    ArcNode * firstedge;
}VNode;

void createAdjList(VNode *&L,int n,int m);
void Dijkstra(int *&d,VNode *&L,int n);
void HeapSort(int *&d,int *&dsti,int n);
void remove(VNode *&L,ArcNode *s);
void removeAdjList(VNode *&L,int n);

int main()
{
    int n,m,i;
    scanf("%d%d",&n,&m);
    VNode *L;
    createAdjList(L,n,m);
    int *d=(int *)malloc(sizeof(int)*n);
    Dijkstra(d,L,n);
    for(i=1;i<n;i++)
        printf("%d\n",d[i]);
    removeAdjList(L,n);
    free(d);
    return 0;
}

//创建有向图的邻接表
void createAdjList(VNode *&L,int n,int m)
{
    int i,u,v,l;
    L=(VNode *)malloc(sizeof(VNode)*n);
    for(i=0;i<n;i++)
    {
        L[i].data=i;
        L[i].firstedge=NULL;
    }
    for(i=0;i<m;i++)
    {
        scanf("%d%d%d",&u,&v,&l);
        ArcNode *s=(ArcNode *)malloc(sizeof(ArcNode));
        s->dst=v;s->nextarc=NULL;s->value=l;
        if(!L[u].firstedge)
            L[u].firstedge=s;
        else
        {
            ArcNode *t=L[u].firstedge;
            while(t->nextarc)
                t=t->nextarc;
            t->nextarc=s;
        }
    }
}

//带堆优化的Dijkstra算法
void Dijkstra(int *&d,VNode *&L,int n)
{
    int i;
    //dsti存放到各目标顶点的编号
    int * dsti=(int *)malloc(sizeof(int)*n);
    for(i=0;i<n;i++)
    {
        dsti[i]=i;
        d[i]=INF;
    }
    //初始化到各点的距离
    d[0]=0;
    ArcNode *t=L[0].firstedge;
    while(t)
    {
        d[t->dst]=t->value;
        t=t->nextarc;
    }
    for(i=n-1;i>=2;i--)
    {
        HeapSort(d,dsti,i);
        ArcNode *s=L[dsti[1]].firstedge;
        while(s)
        {
            if(d[s->dst]>d[dsti[1]]+s->value)
                d[s->dst]=d[dsti[1]]+s->value;
            s=s->nextarc;
        }
        int temp=dsti[1];
        dsti[1]=dsti[i];
        dsti[i]=temp;
    }
}

//堆排序——最小堆,n为参与堆排序的元素的个数
void HeapSort(int *&d,int *&dsti,int n)
{
    int i,j;
    for(i=n/2;i>=1;i--)
    {
        int num=dsti[i];
        for(j=i*2;j<=n;j=j*2)
        {
            if(j+1<=n&&d[dsti[j]]>d[dsti[j+1]])
                j++;
            if(d[dsti[j]]>d[num])
                break;
            dsti[j/2]=dsti[j];
        }
        dsti[j/2]=num;
    }
}

//释放一行邻接表所占空间
void remove(VNode *&L,ArcNode *s)
{
    if(!s)
        return ;
    while(s)
    {
        remove(L,s->nextarc);
    }
    free(s);
}

//删除整个邻接表所占空间
void removeAdjList(VNode *&L,int n)
{
    int i;
    for(i=0;i<n;i++)
    {
        ArcNode *s=L[i].firstedge;
        remove(L,s);
    }
    free(L);
}
    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/qianchangdiyin/article/details/44280533
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞