排序算法之堆排序
2014-04-27 21:09
120 查看
堆是一种数据结构,可以把堆看成一颗完全二叉树。这个二叉树满足:任何一个非叶结点的值都不大于(或不小于其左右孩子结点的值),若父结点大则为大顶堆,若父节点小则为小顶堆。
堆的定义知,根节点是的最是最大的(或最小的),因此将一个无序的序列调整为一个堆,就可以找出这个序列的最大(最小值)。
堆排序的执行过程如下:(大顶堆)
1) 从无序序列所确定的完全二叉树的第一个非叶子结点开始,从右到左,从下至上,对每个结点进行调整,最终将得到一个大顶堆。
对结点的调整方法:将当前结点(假设为a)的值与其孩子结点进行比较,如果存在大于a值的孩子结点,则从中选出一个最大的一个与a交换。当a来到下一层的时候重复上述过程,直到a的孩子结点的值都小于a的值为止。
2)将当前无序序列中第一元素,反映在树中是根结点(假设为a)与无序序列中最后一个元素交换,假设为b。a进入有序序列,到达最终位置。无序序列中的元素减少1个,有序序列中的元素增加一个,此时中有结点b可能不满足堆的定义对其进行调整。
3)重复2)的过程,知道无序序列中的元素剩下一个是排序结束。
大顶堆的代码如下:
小顶堆代码如下:
堆的定义知,根节点是的最是最大的(或最小的),因此将一个无序的序列调整为一个堆,就可以找出这个序列的最大(最小值)。
堆排序的执行过程如下:(大顶堆)
1) 从无序序列所确定的完全二叉树的第一个非叶子结点开始,从右到左,从下至上,对每个结点进行调整,最终将得到一个大顶堆。
对结点的调整方法:将当前结点(假设为a)的值与其孩子结点进行比较,如果存在大于a值的孩子结点,则从中选出一个最大的一个与a交换。当a来到下一层的时候重复上述过程,直到a的孩子结点的值都小于a的值为止。
2)将当前无序序列中第一元素,反映在树中是根结点(假设为a)与无序序列中最后一个元素交换,假设为b。a进入有序序列,到达最终位置。无序序列中的元素减少1个,有序序列中的元素增加一个,此时中有结点b可能不满足堆的定义对其进行调整。
3)重复2)的过程,知道无序序列中的元素剩下一个是排序结束。
大顶堆的代码如下:
#include<stdio.h> void Shift(int r[],int low,int high) { int i=low,j=2*i;//r[j] is the LeftChild int temp=r[i]; while(j<=high) { if(j<high && r[j]<r[j+1]) ++j; if(temp<r[j]) { r[i]=r[j]; i=j; j=2*i; } else break; } r[i]=temp; } void BigHeapSort(int r[],int n) { int i,temp; for(i=n/2;i>=1;--i) Shift(r,i,n);// Initial BigHeap for(i=n;i>=2;--i) { temp=r[1]; r[1]=r[i]; r[i]=temp; Shift(r,1,i-1); } } void main() { int i; int a[11]={0,4,3,2,1,0,7,6,5,8,9};//下标从1开始 BigHeapSort(a,10); for(i=1;i<=10;++i) printf("%d ",a[i]); }
小顶堆代码如下:
#include<stdio.h> void static Shift(int r[],int low,int high) { int i=low,j=2*i,temp=r[i]; while(j<=high) { if(j<high && r[j]>r[j+1]) ++j; if(temp>r[j]) { r[i]=r[j]; i=j; j=2*i; } else break; } r[i]=temp; } void LittleHeapSort(int r[],int n) { int i; int temp; for(i=n/2;i>=1;--i) Shift(r,i,n); for(i=n;i>=2;--i) { temp=r[1]; r[1]=r[i]; r[i]=temp; Shift(r,1,i-1); } } void main(void) { int i; int a[11]={0,2,1,3,5,4,8,7,6,9,0}; LittleHeapSort(a,10); for(i=1;i<=10;++i) printf("%d ",a[i]); }