SSL_1271&&P1177【排序】

排序

题目

P1177


解析

堆排

显然易见的O(nlogn)排序模板,但我们使用堆排,每次取出堆顶输出即可
这里讲一个O(n)建堆法:首先将n个数直接赋给堆中对应的下标,不维护堆性质,然后从n/2循环到1,down(i),最终可以形成堆,但它是O(n)的
虽然说没什么用,因为每次取出还是O(logn)的……
1672K/15MS
最优解!

code:

#include<cstdio>
using namespace std;
inline void swap(int &x,int &y){
    
    x^=y^=x^=y;}
inline bool idigit(char x){
    
    return (x<'0'|x>'9')?0:1;}
inline int read()
{
    
    
	int num=0,f=1;
	char c=0;
	while(!idigit(c=getchar())){
    
    if(c=='-')f=-1;}
	while(idigit(c))num=(num<<1)+(num<<3)+(c&15),c=getchar();
	return num*f;
}
inline void write(int x)
{
    
    
	int F[20];
	int tmp=x>0?x:-x;
	if(x<0)putchar('-');
	int cnt=0;
	while(tmp>0){
    
    F[cnt++]=tmp%10+'0';tmp/=10;}
	while(cnt>0)putchar(F[--cnt]);
	if(x==0)putchar('0');
	putchar(' ');
}
int n,heap[100010],r,tot;
inline void down(int x)
{
    
    
	while((x<<1)<=tot)
	{
    
    
		if((x<<1|1)<=tot&&heap[x<<1]>heap[x<<1|1])r=(x<<1|1);
		else r=(x<<1);
		if(heap[x]>heap[r])swap(heap[x],heap[r]),x=r;
		else break;
	}
}
int main()
{
    
    
	n=read(),tot=n;
	for(int i=1;i<=n;++i)heap[i]=read();
	for(int i=(n>>1);i;--i)down(i);
	while(tot)write(heap[1]),heap[1]=heap[tot--],down(1);
	return 0;
}

快排

快排的实现基于分治思想,其特点是可以退化为n方常数小
具体实现参见代码
1780K/93MS

code:

#include<cstdio>
#include<iostream>
using namespace std;
int n,a[100001];
void srt(int l,int r)
{
    
    
	int mid=a[l+r>>1],i=l,j=r;//日常位运算卡常
	while(i<=j)
	{
    
    
		while(a[i]<mid)i++;
		while(a[j]>mid)j--;//左右移
		if(i<=j)
		{
    
    
			swap(a[i],a[j]);//交换
			i++;
			j--;
		}
	}
	if(l<j)srt(l,j);
	if(i<r)srt(i,r);//递归
}
int main()
{
    
    
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	srt(1,n);
	for(int i=1;i<=n;i++)printf("%d ",a[i]);
	return 0;
}

归并排

归并排需要一个额外的数组,当数组大小不为一时将数组分成两半递归归并排,并利用额外空间不断取出较小值,最后赋回去
2084K/109MS

code:

#include<cstdio>
#define rr register int
using namespace std;
int n,a[100010],b[100010];
inline void gb(int l,int r)
{
    
    
	if(l==r)return;
	rr mid=l+r>>1,p=l,j=mid+1,i=l;
	gb(l,mid),gb(j,r);//递归排序
	while(l<=mid&&j<=r)b[p++]=(a[j]>a[l])?a[l++]:a[j++];//选较小者取
	while(l<=mid)b[p++]=a[l++];
	while(j<=r)b[p++]=a[j++];//清空剩余
	for(;i<=r;++i)a[i]=b[i];
}
int main()
{
    
    
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	gb(1,n);
	for(int i=1;i<=n;++i)printf("%d ",a[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zhanglili1597895/article/details/115095800