堆,其实就是一棵完全二叉树。堆排序中,主要利用的是大顶堆,即父节点的值大于或者等于子节点的值。
堆排序的核心思想,就是调整堆为大顶堆,然后将最首的点和堆最尾的点值进行交换,那么堆尾的点就为最大的值;然后对去除堆尾的堆进行调整,调整为大顶堆,那么堆顶就是第二大的点,那么将它与这个新堆的堆尾的点的值进行交换,那么这个堆尾的值就是第二大的值;反复进行,最后从堆首到堆尾进行输出,即得到数的由小到大的顺序。
堆的性质:
1.父节点的下标为i,那么左子节点如果存在,那么下标为2*i;右子节点如果存在,那么下标为2*i+1
2.堆的最后一个含有子树的节点的下标为heapSize/2(heapSize为堆的大小)
这两条性质都是在下标从1开始的情况下成立
代码如下:
#include<iostream>
using namespace std;
//此算法为堆排序,很明显,时间复杂度为nlog(n)
//交换两个数字
void swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
}
//调整根节点为i的子树为大顶堆
void HeapINF(int *a,int i,int heapSize)
{
int l=2*i;
int r=2*i+1;
int large=i;
if(l<=heapSize&&a[l]>a[i])
{
large=l;
}
if(r<=heapSize&&a[r]>a[large])
{
large=r;
}
if(large!=i)
{
swap(a[i],a[large]);
HeapINF(a,large,heapSize);
}
}
//建立大顶堆
void BuildMAXHeap(int *a,int num)
{
for(int i=num/2;i>=1;i--)
{
HeapINF(a,i,num);
}
}
//堆排序
void HeapSort(int *a,int num)
{
BuildMAXHeap(a,num);
for(int i=num;i>=2;i--)
{
swap(a[1],a[i]);
HeapINF(a,1,i-1);
}
}
int main()
{
int num;
cout<<"请输入数字的个数:"<<endl;
cin>>num;
cout<<"请输入数字:"<<endl;
int *a=new int[num+1];
for(int i=1;i<=num;i++)
{
cin>>a[i];
}
HeapSort(a,num);
for(int i=1;i<=num;i++)
{
cout<<a[i]<<" ";
}
delete a;
system("pause");
return 0;
}