选择排序之堆排序

    技术2025-07-18  13

    堆排序,在排列的过程中将元素看成完全二叉树的结构,利用双亲结点和子节点之间的关系,找出最大(或小)的元素。

    双亲结点为Ri,则其左孩子和右孩子分别为R2i,R(2i+1),利用这一点关系,通过构造堆的方法排序。

    假设我们要输出从小到大的排列,那么可以构造大根堆,即寻找堆的最大元素,上浮到根节点(还有就是保证双亲结点大于孩子节点),再将跟点与最后一个叶子结点交换,接着去除最后一个叶子结点,堆剩下的堆重新筛选,找出最大元素,上浮到根节点,与最后一个叶子结点交换......一直循环到堆只剩下一个结点。如何构造和筛选大根堆?

    选择最后一个双亲结点位置(i=len/2),让孩子结点中的最大者与双亲结点进行比较(即R[2i]和R[2i+1]中的最大者与R[i]比较),如果孩子结点大,则相互交换位置,接着选择上一个双亲结点,继续进行比较,一直循环知道第一个双亲结点的比较完成。

    而比较过程中会进行筛选,即当出现了交换位置的情况,那个被交换位置的那个孩子结点要和它的孩子结点再进行比较,这样才能确保所有的双亲结点都大于它的孩子结点。

    代码如下:

    2011-02-14 UNIX环境

    #include <stdio.h> #include <stdlib.h> void BuildHeap(int a[], int len,int low) { int i,j,temp; i = low; j =2*i; while(j <= len) { temp = a[i-1];//temp等于双亲结点的值 if(j < len && a[j] > a[j-1])//若右孩子结点大于做孩子结点,那么j+1表示接下来双亲结点要与右孩子结点比较 j++; if(a[j-1] > temp) { a[i-1] = a[j-1];//将大的数与其双亲结点交换位置 a[j-1] = temp; i=j;//调整i的值,继续向下筛选 j=2*i; } else break; } } void HeapSort(int a[], int len) { int i,temp,j; for(i=len/2; i >=1; i--)//建立初始大根堆 BuildHeap(a,len,i); for(i = len;i >= 2; i--)//len-1次循环 { temp = a[0]; a[0] = a[i-1];//第一个元素与堆中最后一个调换 a[i-1] = temp; BuildHeap(a,i-1,1); } } void print(int a[], int len) { int i; for(i = 0; i < len; i++) printf("%d/n", a[i]); } int main(int arc, char *argv[]) { int len; int a[] = {6,8,7,9,0,1,3,2,4,5,99,87,9898,6765,111,567}; len = sizeof(a)/sizeof(int); HeapSort(a, len); print(a, len); return 0; }

       

     

     

    最新回复(0)