Description
输入n(<=100000),由小到大输出
Input
n
n个数
Output
由小到大输出
Sample Input
5
3 2 1 4 5
Sample Output
1 2 3 4 5
思路
明明是sort可以解决的事情,为啥要堆啊
堆主要操作有交换,查询最值,删除某个值
我们要让堆保持有序性,即父节点比所有其子节点都大/小
所以我们需要用交换把堆弄成有序的,即排序。
那么如何交换?
先放一趟排序的代码:
void f(long long x,long long n)
{
long long y=x*2+1;
while (y<n)
{
if (y+1<n&&v[y]<v[y+1]) y++;
if (v[x]<v[y])
{
swap(v[x],v[y]);
x=y;
}
y*=2;
y++;
}
return;
}
正如你所见,这里的一次交换都是父节点取最大,然后把与其交换的点重复交换。
但是!从倒数第2层开始以每一个点为起点都需要一趟排序!
所以是O(nlogn),其基于交换,是稳定的!
code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<map>
using namespace std;
long long v[100001];
long long n;
void f(long long x,long long n)
{
long long y=x*2+1;
while (y<n)
{
if (y+1<n&&v[y]<v[y+1]) y++;
if (v[x]<v[y])
{
swap(v[x],v[y]);
x=y;
}
y*=2;
y++;
}
return;
}
int main()
{
cin>>n;
for (long long i=0;i<n;i++) cin>>v[i];
for (long long i=n/2-1;i>=0;i--) f(i,n);
for (long long i=n-1;i>0;i--)
{
swap(v[i],v[0]);
f(0,i);
}
for (long long i=0;i<n;i++) cout<<v[i]<<' ';
return 0;
}