SSLOJ1271 排序I

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;
}

猜你喜欢

转载自blog.csdn.net/weixin_49843717/article/details/115014517
今日推荐