堆排序是选择排序的一种改进。
堆是一种特殊的完全二叉树:每个节点的值都小于或等于其左右子节点的值(小顶堆),反之为大顶堆。
堆排序的关键是:创建堆和抽掉堆顶之后的堆重建。
注意:设n个数据在数组a[1]~a[n]中,当前要筛选的节点编号为k,堆中最后一个节点的编号为m,且k的左右子树均为堆。
template<class Type> void Shift(Type a[],int k,int m) { int i=k; int j=2*i; while(j<=m) { if(j<m&&a[j]<a[j+1]) j++; //j为k节点的左右孩子中值较大的下标 if(a[i]>a[j]) break; else { Type tem=a[i]; a[i]=a[j]; //节点k与左右孩子中较大的交换位置 a[j]=tem; i=j; j=2*i; } } }
初始键堆,即从n/2开始,筛选节点,直到a[1]
for(int i=n/2;i>=1;i--) { Shift(a,i,n); }
最终代码实现:
#include<iostream> using namespace std; //数据存储在a[1]-a[n]中,a[0]中不是需要排序的数据 template<class Type> void Shift(Type a[],int k,int m) { int i=k; int j=2*i; while(j<=m) { if(j<m&&a[j]<a[j+1]) j++; if(a[i]>a[j]) break; else { Type tem=a[i]; a[i]=a[j]; a[j]=tem; i=j; j=2*i; } } } template<class Type> void HeapSort(Type a[],int n) { for(int i=n/2;i>=1;i--) { Shift(a,i,n); } cout<<a[1]<<" "<<a[n]<<endl; Type tem; for(int i=1;i<n;i++) { tem=a[1]; a[1]=a[n-i+1]; a[n-i+1]=tem; // cout<<a[n+1-i]<<" "; Shift(a,1,n-i); } } int main() { int a[9]={0,36,30,18,40,32,45,22,50}; for(int i=0;i<9;i++) cout<<a[i]<<" "; cout<<endl; HeapSort(a,8); for(int i=0;i<9;i++) cout<<a[i]<<" "; cout<<endl; return 0; }