堆排序是选择排序的一种改进。
堆是一种特殊的完全二叉树:每个节点的值都小于或等于其左右子节点的值(小顶堆),反之为大顶堆。
堆排序的关键是:创建堆和抽掉堆顶之后的堆重建。
注意:设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;
}