几种排序算法的对比

!
最近干了一些有意思的事情:拿出来写一写

关于各种sort!

比如,c++自带的快排,归并排序,还有stdlib库里面的qsort

还有我自己实现的二进制基排,65536进制基数排序,普通归并排序,FFT式归并排序

以及基于队列实现的queue-mergesort(其实本质还是mergesort啦)

目前测试结果来看,表现最好的,应该是普通归并排序(65536基排不算),排序 1 0 7 10^7 107个数字只用了1.1s,让后就是queue-mergesort

反正各种快排没有那么优秀啦,加上O3还是没有mergesort快

解释一下这个queue-mergesort
首先,每个数作为一个独立的“块”放入队列中,每次取出开头的两个“块”进行合并让后丢到队尾,容易看出这个算法复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)

算法本身需要用到循环队列进行辅助操作,让后为了减小常数,取模使用位运算代替,这就意味着要牺牲一部分空间作为代价,同时,为了记录各个块的信息,还要额外开一个数组记录

不过这个算法的思想还是很不错的
放一个code上来

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#define SIZ 10000000
using namespace std;
unsigned s[20000001],b[33554431],*w=s;
inline int mkd(){
	for(int T=SIZ;T;--T)
		s[T]=(s[T+1]*3859+65492)^235993592ll;
}
int cmp(const void* a,const void* b){
	return *(unsigned*)a<*(unsigned*)b?-1:1;
}
inline void radix(int V,int n=10000000){
	int c[65536]={0};
	for(int i=1;i<=n;++i) ++c[s[i]>>V&65535];
	for(int i=1;i<65536;++i) c[i]+=c[i-1];
	for(int i=n;i;--i) b[c[s[i]>>V&65535]--]=s[i];
	memcpy(s+1,b+1,n<<2);
}
inline void merge(int l,int r){
	if(l<r){
		register int m=l+r>>1,i=l,j=m+1,t=l;
		merge(l,m); merge(m+1,r);
		for(;i<=m && j<=r;)
			b[t++]=(s[i]<=s[j]?s[i++]:s[j++]);
		for(;i<=m;b[t++]=s[i++]);
		for(;j<=r;b[t++]=s[j++]);
		memcpy(s+l,b+l,r-l+1<<2);
	}
}
inline void split(int l,int r,unsigned V){
	if(l<r){
		int i=l,j=r;
		for(;i<j;){
			for(;i<j&&s[j]&V;--j);
			for(;i<j&&~s[i]&V;++i);
			if(i<j) s[i]^=s[j]^=s[i]^=s[j];
			else{ s[j]&V?--i:++j; break; }
		}
		V>1?split(l,i,V>>1),split(j,r,V>>1):(void)0;
	}
}
inline void FFT(int n){
	int m; for(m=1;m<n;m<<=1);
	for(int i=m;i>n;--i) s[i]=-1;
	register unsigned *S=s,*B=b;
	for(register int L=2,M=1,l,i,j;M<m;L<<=1,M<<=1){
		for(l=0;l<m;l+=L,S+=L){
			for(i=1,j=M+1;i<=M&&j<=L;)
				*++B=(S[i]<=S[j]?S[i++]:S[j++]);
			for(;i<=M;*++B=S[i++]);
			for(;j<=L;*++B=S[j++]);
		}
		S-=m; B-=m;	swap(S,B);
	}
} 
inline void chk(){
	for(int i=1;i<SIZ;++i)if(s[i]>s[i+1]) 
	puts("#");
	puts("Pass");
}
inline void qusort(int n){
	const int m=33554431;
	register int H=0,T=-1,t=n,l,r,M,i,j;
	memcpy(b+1,s+1,n<<2);
	for(int i=1;i<=n;++i) w[++T]=i;
	for(;H<T;){
		l=w[H++]; M=w[H++]; w[++T]=t+1&m; r=w[H]; 
		for(i=l,j=M;(i&m^M)&&(j&m^r);)
			b[++t&m]=(b[i&m]<=b[j&m]?b[i++&m]:b[j++&m]);
		for(;i&m^M;b[++t&m]=b[i++&m]);
		for(;j&m^r;b[++t&m]=b[j++&m]);
	}
	t=w[T];
	for(int i=0;i<n;++i) s[i+1]=b[i+t&m];
}
int main(){
	mkd();
	qsort(s+1,10000000,4,cmp);
	FFT(10000000);
	sort(s+1,s+10000001);
	stable_sort(s,s+1+10000001);
	radix(0); radix(16); 
	merge(1,10000000);
	split(1,10000000,1u<<31);
	qusort(SIZ);
	chk();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值