此题题目描述有误,因为要求用堆排序求非递减序列,但只进行一趟(建立大根堆),但题目给出的样例答案却是一个小根堆,而完成整个堆排序的话得到的序列正是一个递减序列,所以。。。还是不管题目描述吧。。。建一个小根堆就好了
具体堆排序的算法请点击这里(步骤过于复杂,还是直接转载吧,而且这可以说是我能找到的最详细清晰的讲解了):
http://www.cnblogs.com/chengxiao/p/6129630.html#3959112
递增:建大根堆
递减:建小根堆(因为排序是通过根节点来找最大、最小值然后与当前数组尾进行交换来实现的)
#include<iostream>
using namespace std;
void adjust_big(int arr[],int i,int lenth)//建立(调整)小根堆
{
int temp=arr[i];
for(int k=i*2;k<lenth;k*=2)
{
if(k+1<lenth&&arr[k+1]<arr[k]) //找左右孩子最小的一个
k++;
if(arr[k]<temp) //小元素上浮,一定要注意这里是要比temp小,不是跟arr[i]作比较!
{
arr[i]=arr[k];
i=k;
}
else break;
}
arr[i]=temp;
}
void exc(int arr[],int i,int j) //用于交换根(最大值)和尾(最小值)这里因为只跑一趟 所以用不到
{
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
int main()
{
int n;
cin>>n;
int arr[n+1];
for(int i=1;i<=n;i++)
cin>>arr[i];
for(int i=n/2;i>0;i--) //不论大根堆还是小根堆注里都要从最后一个非叶子节点开始从下往上跑
adjust_big(arr,i,n+1);
/*for(int i=n;i>1;i--)
{
exc(arr,1,i);
adjust_big(arr,1,i);
} */
for(int i=1;i<=n;i++)
cout<<arr[i]<<" ";
return 0;
}