主要思想:在选取当前距离最小点时,用堆的方法实现选最小点上时间的优化。 新手第一次写,各种被坑!!! 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; }