思路:
堆排序主要分为俩个部分,一个是构建堆(主要的,根节点下的俩个子节点大小差距不一定,其子节点不一定按顺序排),另外一个是调整堆。
构建堆(第一个for循环,自下而上)之后,初步的顺序出来了,堆顶便是最大的值,我们将他定为老大,俩个子节点为老二,俩个老二分别代表俩个分支,他们分别是俩个分支中的最强者(一人之下万人之上的老二之一)。但是这俩个左右分支实力不得而知,可能左节点下一个堂口的小弟便强于右节点的老二。不过可以确定的是,真正的第二强者在他们俩个之间。就在目前这个时期,我们是处于第一个FOR循环之中。
到了第二个FOR循环,我们要将老大(top)放入名人堂中,他下岗,我们的第二强者上岗成为新的老大。不过在此之前,我们只有一个数组,那么我们要将小弟们(tail堆尾,也就是数组的尾部)的地方腾出来【swap(0,j)】,将小弟(tail)放入老大的位置而后,让各个分支、堂口去检验(也就是慢慢被刷回去,回到解放前 = =!!,adjustHeap(0,j)这个过程是自上而下的)。那么,俩个分支的老大会有一个成为新的top,他所在分支的俩个老三(堂主)会有一个成为新的分支老大,以此类推(可怜的小弟......)。然后老大不断进入”名人堂“,小弟渐渐没有,帮派灭亡,排序完成。
过程中注意几个循环体的参数。
构建堆:
从length/2-1开始调整length/2-1次方能构建大顶堆。因为length/2-1开始才有叶子结点(从下至上,从右至左调整结构 )。
调整:adjustHeap(i,length) ——调整i(有叶子节点的节点)及其子节点的叶子节点(for(k=i*2+1;k<length;k=k*2+1) ),将其调整为父节点最大,其次左节点,右节点,(层次排序)。
便于理解构建堆的图解:https://www.cnblogs.com/chengxiao/p/6129630.html
便于理解调整的图解:https://www.cnblogs.com/MOBIN/p/5374217.html。看了好几个博客,这俩个各有所长。
构建堆与调整堆: 最初的多次调整构建堆,后面微调,原本调好的顺序(分支)还记录在堆结构里面,避免重复换位这也是堆排序,堆结构的意义所在。 平均时间复杂度:O (nlgn)
#include <stdio.h> int static arr[] = {9,8,11,6,5,4,3,2,1}; void sort(){ //构建大堆顶 int length = sizeof(arr)/sizeof(int); int i,j; for(i=length/2-1;i>=0;i--) //length/2-1开始才有子节点 { //从第一个非叶子节点从下至上,从右至左调整结构,分支大小差距不知 adjustHeap(i,length); //构建大顶堆 } //2、调整堆结构和交换堆顶元素与末尾元素 for(j=length-1;j>0;j--) { swap(0,j); //将堆顶元素与末尾元素交换,将堆顶放到堆尾,然后重新构建大顶堆(原有基础上),堆尾就不用管了,所以这里是j--,表示一个top进入名人堂,少了一个小弟 adjustHeap(0,j); // 重新对堆进行调整,调整时,从堆顶往下调(构建大顶堆)所以此时i是0,堆顶下面的俩个分支是已经调好的,然后如果新的堆顶很小那他会一直被换到底部(可能进入另外一个分支当老大),保证最强者是俩个分支的老大。 } } void adjustHeap(int i,int length) { int temp = arr[i]; int k; /**一个for循环比较一个父节点和他的子节点们(俩个)**/ for(k=i*2+1;k<length;k=k*2+1) // k=i*2+1即为i的左叶子节点,k=k*2+1,该节点的子节点如果有叶子节点的话,继续比较,直至者一支/堂/...比较完 { if(k+1<length && arr[k]<arr[k+1]) // 保证左大于右 { k++; } if(arr[k]>temp) // 如果子节点大于父节点,讲子节点赋值给父节点(不用进行交换【其实是交换第一部分】) { arr[i] = arr[k]; i=k; }else{ break; } } arr[i] = temp; //讲temp值放到最终的位置【其实就是交换分俩部分,这是最后一部分】 } void swap(int a,int b) { int t; t = arr[a]; arr[a] = arr[b]; arr[b] = t; } int main() { int i; sort(); int length = sizeof(arr)/sizeof(int); for(i=0;i<length;i++) { printf("%d",arr[i]); } return 0; }