排序算法三之堆排序

来源:互联网 发布:python爬虫 pdf 百度云 编辑:程序博客网 时间:2024/04/28 02:00

   这次介绍堆排序,堆排序分为2步,1.建堆  2.排序 但是建堆的过程是对堆进行调整,而排序的过程实际上也是对堆调整,堆排序,是基于完全二叉树的,凡是和树和图相关的,总是需要多花点时间弄懂,哎,基础太差。

    所以关键是对堆的调整,下面的代码和图用的是大顶堆,代码是参考大话数据结构,理解了之后自己动手敲的。

   调整的过程如下图所示,但是为了显示一个过程,图7、图8最后的虚线是visio一页不足所致,红色为每次要调整的非叶子结点


排序的过程就是,每次拆掉最后一个结点,然后重新调整堆,见下图


另外需要注意的地方都在代码注释中

void heapAdjust(int a[],int n,int s){int tmp=a[s],i;for(i=2*s;i<=n;i*=2){          //1.i=2*s,是因为当前节点是s,那么左孩子一定是2*s      2.为什么是i*=2,也是完全二叉树的性质,每次都是往下比较孩子结点的值if(i<n&&a[i]<a[i+1])  i++;   //比较左孩子和右孩子,看谁大if(tmp>=a[i])  break;         a[s]=a[i];              //调整比父节点大的值,赋值的过程如上图s=i;             }a[s]=tmp;         //最后调整原来的值应该所在的位置}void heapSort(int a[],int n){int i;for(i=n/2;i>=1;i--){           //建堆heapAdjust(a,n,i);}for(i=n;i>1;i--){              //排序swap(&a[1],&a[i]);heapAdjust(a,i-1,1); }} 
堆排序总结:

1.堆排序,下标是从1开始的,以前的六种排序可以从0开始也可以从1开始,因为按照完全二叉树的性质,如果1是父节点,那么2和3是他的子节点,如果从0开始的话,那么就是1和2是他的父节点,不满足2*i和2*i+1,反映在代码上就是heapAdjust函数中的for循环的第一个if语句中,i会变成0或者1,而不是预想的1和2,所以堆排序全部是从1到n,a[0]舍弃不用

2.建堆的过程中应该注意,如果有n个数,只需要<=n/2遍即可,因为<=n/2的节点都是非叶子结点,比如完全二叉树,当n=7,那么这个树的叶子结点是4,5,6,7,非叶子结点也就是1,2,3,把1,2,3的节点调整完毕,则整棵树也就满足大顶堆的定义:每个结点的值都大于等于其左右孩子叶子结点的值,反映在代码上就是heapSort函数中的第一个循环
初值是n/2,循环条件是i>=1

3.写代码过程中出错的地方,感觉堆排序过程中,一定要注意各个for循环和if判断中对于边界的判断,for循环还需注意初始值

   heapAdjust函数中的第一for循环中是i<=n,而第一个else循环中是i<n,这是因为数组中最后一个元素是a[n],而if中还要比较a[i]左孩子和a[i+1]右孩子

    heapSort函数中的第二个for循环,最后一个数是a[n],故i=n,只剩一个数时无需调整,所以i>1,始终和第一个结点交换,然后堆调整的heapAdjust(a,i-1,1),第一个参数不解释,第三个参数因为每次都和第一个结点交换,所以每次都调整从1开始调整堆,第二个参数原来是i=n个,交换了一个,得到了一个最大值,然后下一次调整的时候边界就是i-1了。


总的代码如下:

#include <stdio.h>#include <stdlib.h>#include <time.h>#define MAXN 15void display(int a[],int n){int i;for(i=1;i<=n;i++){printf("%d ",a[i]);}printf("\n");}void swap(int *s,int *t){int temp=*s;*s=*t;*t=temp;}void heapAdjust(int a[],int n,int s){int tmp=a[s],i;for(i=2*s;i<=n;i*=2){          if(i<n&&a[i]<a[i+1])  i++;   if(tmp>=a[i])  break;         a[s]=a[i];              s=i;             }a[s]=tmp;        }void heapSort(int a[],int n){int i;for(i=n/2;i>=1;i--){heapAdjust(a,n,i);}for(i=n;i>1;i--){swap(&a[1],&a[i]);heapAdjust(a,i-1,1); }}  int main(int argc, char *argv[]) {unsigned int seed;     seed = time(0);     srand(seed);int i,a[MAXN];for(i=1;i<MAXN;i++){a[i]=rand()%100+1;}display(a,MAXN-1);heapSort(a,MAXN-1);display(a,MAXN-1);return 0;}

未完待续,还有排序算法的总结

如需参考排序算法总结排序算法四总结


如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步

文章转载请注明出处,请尊重知识产权

0 0