dijkstra算法+堆优化 ///各种被坑~~~

主要思想:在选取当前距离最小点时,用堆的方法实现选最小点上时间的优化。 新手第一次写,各种被坑!!! 1、一定要用最小堆从堆顶取值,而不能用最大堆取排在最后的值,因为排在最后的值不一定是最小的。 2、因为不能在调整堆的时候直接改变dis[]的值(如果改变的话在输出的时候会乱掉..),所以应该只是借助dis[]的值去调整顶点的位置,所以需要一个数组(从1到n代表堆的位置,每个位置保存当前在这个位置上的顶点编号)。而函数需要传入该顶点所在的堆的位置,所以有需要一个数组(从1到n代表每个顶点,每个位置保存该顶点所在堆中的位置。) 3、从堆顶取值和最后交换,在将堆顶shiftdown。 4、中间更改了某一个点的dis值后,需要将这个点shiftup。 5、最最最被坑的一点,感觉自己智商堪忧,竟然在把局部变量改成全局变量时,忘记删掉原来的局部变量了(………………………………….)几乎将每一步都printf出来才发现这个问题。

#include #include ///变量重复定义坑 int num[10],dis[10],pos[10]; void shift_down(int a,int n) {     int t,temp;     int flag=1;     while(2*a<=n&&flag==1)     {         printf(“i=%d进行判断:\n”,a);         printf(“num:%d %d %d\n”,num[a],num[2*a],num[2*a+1]);         printf(“dis:%d %d %d\n”,dis[num[a]],dis[num[2*a]],dis[num[2*a+1]]);         if(2*a<=n)///这个判断条件要注意单独写出来,如果和下面的条件一起判断,可能会在不应该改变的时候将t的值改变了。         {             if(dis[num[a]]>dis[num[2*a]])               {                 t=2*a;               }             else             {                  t=a;             }         }         if((2*a+1)<=n)         {             if(dis[num[t]]>dis[num[2*a+1]])                 t=2*a+1;         }         if(t!=a)         {             flag=1;              ///交换了堆上每个位置保存的定点编号             temp=num[a];             num[a]=num[t];             num[t]=temp;             ///交换了每个顶点在堆上的位置             temp=pos[num[a]];             pos[num[a]]=pos[num[t]];             pos[num[t]]=temp;             ///很重要             printf(“交换了一次\n”);             a=t;         }         else         {             flag=0;         }     } } void shift_up(int a) {     int t,temp;     while(a!=1&&dis[num[a]]<dis[num[a/2]])     {             t=a/2;            ///交换了堆上每个位置保存的定点编号             temp=num[a];             num[a]=num[t];             num[t]=temp;             ///交换了每个顶点在堆上的位置             temp=pos[num[a]];             pos[num[a]]=pos[num[t]];             pos[num[t]]=temp;             a=t;    } } int main() {    int e[10][10];    int m,n,i,j,k,count;    int x,y,z;    int inf=999999;    int temp;    scanf(“%d %d”,&n,&m);    for(i=1;i<=n;i++)        for(j=1;j<=n;j++)        {            e[i][j]=inf;        }    for(i=1;i<=m;i++)    {        scanf(“%d %d %d”,&x,&y,&z);        e[x][y]=z;    }    for(i=1;i<=n;i++)    {        dis[i]=e[1][i];        //book[i]=0;        num[i]=i;///堆上每个位置的顶点编号        pos[i]=i;///每个定点在堆上的位置    }    dis[1]=0;    printf(“\n”);    count=n;    ///建立一个最小堆    /*dis[1]=6;    dis[2]=5;    dis[3]=4;    dis[4]=3;    dis[5]=2;    dis[6]=1;*/    for(i=1;i<=n;i++)    {        printf(“距离为:%d “,dis[i]);    }    printf(“\n”);    for(i=1;i<=n;i++)    {        printf(“num为:%d “,num[i]);    }    printf(“\n”);    for(i=n;i>=1;i–)    {        shift_down(i,count);    }    printf(“test:”);    for(i=1;i<=count;i++)    {        printf(“%d “,num[i]);    }    printf(“\n”);    while(count!=0)    {        for(i=1;i<=count;i++)        {            printf(“%d “,num[i]);        }        printf(“\n”);        temp=num[1];        num[1]=num[count];        printf(“%d\n”,temp);        count–;        shift_down(1,count);        for(i=1;i<=count;i++)        {            printf(“%d “,num[i]);        }        printf(“\n”);printf(“\n”);        for(k=1;k<=n;k++)        {            if(e[temp][k]<inf)            {                if((dis[temp]+e[temp][k])<dis[k])                {                    dis[k]=dis[temp]+e[temp][k];                    ///调整最小堆                    shift_up(pos[k]);                }            }        }    }    printf(“最终距离:”);    for(i=1;i<=n;i++)    {        printf(“%d “,dis[i]);    }    getchar();getchar();     return 0; }

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/lijiashushu/article/details/60340672
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞