鉴于快速排序难以分析的复杂度和对stl的极度不信任做了一下尝试。
数据生成器
#include<iostream>
#include<cstdio>
#include<time.h>
#include<stdlib.h>
using namespace std;
FILE *ans = fopen("ans.out","w");
int cnt=0;
void solve(){
FILE *fp = fopen("1.in","w");
int n = rand()%1000000+1000000;
fprintf(fp,"%d\n",n);
for(int i=1;i<=n;i++){
fprintf(fp,"%d\n",rand()%10000);
}
fclose(fp);
system("fast");
system("merge");
system("fast_hand");
FILE *fp1 = fopen("1.out","r");
FILE *fp2 = fopen("2.out","r");
FILE *fp3 = fopen("3.out","r");
int cnt_1,cnt_2,cnt_3,t_1,t_2,t_3;
fscanf(fp1,"%d %d",&cnt_1,&t_1);fscanf(fp2,"%d %d",&cnt_2,&t_2);
fscanf(fp3,"%d %d",&cnt_3,&t_3);
// printf("%d %d %d %d %d %d\n",t_1,t_2,t_3,cnt_1,cnt_2,cnt_3);
fprintf(ans,"size %d,time %d %d %d,cnt %d %d %d\n",n,t_1,t_2,t_3,cnt_1,cnt_2,cnt_3);
}
int main(){
srand(time(0));
for(int i=1;i<=1000;i++){
cnt=i;
solve();
}
return 0;
}
stl sort
#include<time.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int read(){
int rt=0,fl=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')fl=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){rt=rt*10+ch-'0';ch=getchar();}
return rt*fl;
}
int cnt=0;
struct str{
int ca;
str(){
}
str(int _bu){
this->ca=_bu;
}
bool operator < (str b)const{
cnt++;
return this->ca < b.ca;
}
};
str s[10000000];
int n;
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
n = read();
for(int i=1;i<=n;i++){
int a = read();
s[i] = str(a);
}
sort(s + 1,s + n);
cout<<cnt<<endl<<clock();
return 0;
}
mergesort
#include<bits/stdc++.h>
using namespace std;
int read(){
int rt=0,fl=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')fl=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){rt=rt*10+ch-'0';ch=getchar();}
return rt*fl;
}
int cnt=0,n;
struct str{
int ca;
str(){
}
str(int _bu){
this->ca=_bu;
}
bool operator < (str b)const{
cnt++;
return this->ca < b.ca;
}
};
str s[10000000],buf[10000000];
void init(){
n = read();
for(int i = 1;i < n;i++){
int a = read();
s[i] = str(a);
}
}
void sort(int l,int r){
if(l==r)return;
int mid = l + r >> 1 ,L = l,R = mid+1;
sort(l,mid);sort(mid+1,r);
for(int i = l;i <= r;i++){
if(L<=mid&&R<=r){
if(s[L]<s[R]){
buf[i]=s[L++];
}else{
buf[i]=s[R++];
}
}else if(L<=mid){
buf[i]=s[L++];
}else{
buf[i]=s[R++];
}
}
// for(int i=l;i<=r;i++)s[i]=buf[i];
memcpy(s+l,buf+l,(r-l+1)*sizeof(str));
}
int main(){
freopen("1.in","r",stdin);
freopen("2.out","w",stdout);
init();
sort(1,n);
cout<<cnt<<endl<<clock();
return 0;
}
手写快拍
#include<ctime>
#include<cstdio>
#include<iostream>
using namespace std;
int read(){
int rt=0,fl=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')fl=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){rt=rt*10+ch-'0';ch=getchar();}
return rt*fl;
}
int cnt=0,n;
struct str{
int ca;
str(){
}
str(int _bu){
this->ca=_bu;
}
bool operator < (str b)const{
cnt++;
return this->ca < b.ca;
}
bool operator > (str b)const{
cnt++;
return this->ca > b.ca;
}
};
str a[10000000],buf[10000000];
void init(){
n = read();
for(int i = 0;i < n;i++){
int aa = read();
a[i] = str(aa);
}
}
void quicksort(int left,int right)
{
int i,j;str base;
i=left; j=right;
base=a[(i+j)/2];
while (i<=j){
while (a[i]<base) i++;
while (a[j]>base) j--;
if (i<=j){
str t=a[i]; a[i]=a[j];a[j]=t;
i++;
j--;
}
}
if (left<j) quicksort(left,j);
if (i<right) quicksort(i,right);
}
int main()
{
freopen("1.in","r",stdin);
freopen("3.out","w",stdout);
init();
quicksort(0,n-1);
cout<<cnt<<endl<<clock();
return 0;
}
可以看出,在不开O2优化且数据保证随机的条件下,手写快拍是最快的,但比较次数也是最多的,归并排序虽然耗时最长,但比较次数是最少的,而且少的非常明显。
当然在开启O2优化的情况下,stl的sort是完虐它们的。
为了加大比较次数对时间影响,我把排序的对象换成了字符串。
数据生成器
#include<iostream>
#include<cstdio>
#include<time.h>
#include<stdlib.h>
using namespace std;
FILE *ans = fopen("ans.out","w");
int cnt=0;
void solve(){
FILE *fp = fopen("1.in","w");
int n = rand()%1000000+100000;
fprintf(fp,"%d\n",n);
for(int i=1;i<=n;i++){
int len = rand()%15+2;
for(int j=1;j<=len;j++){
fprintf(fp,"%c",rand()%17+'a');
}
fprintf(fp,"\n");
}
fclose(fp);
system("fast");
system("merge");
system("fast_hand");
FILE *fp1 = fopen("1.out","r");
FILE *fp2 = fopen("2.out","r");
FILE *fp3 = fopen("3.out","r");
int cnt_1,cnt_2,cnt_3,t_1,t_2,t_3;
fscanf(fp1,"%d %d",&cnt_1,&t_1);fscanf(fp2,"%d %d",&cnt_2,&t_2);
fscanf(fp3,"%d %d",&cnt_3,&t_3);
printf("%d %d %d %d %d %d\n",t_1,t_2,t_3,cnt_1,cnt_2,cnt_3);
fprintf(ans,"size %d,time %d %d %d,cnt %d %d %d\n",n,t_1,t_2,t_3,cnt_1,cnt_2,cnt_3);
}
int main(){
srand(time(0));
for(int i=1;i<=10000;i++){
cnt=i;
solve();
}
return 0;
}
stl
#include<time.h>
#include<string>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int read(){
int rt=0,fl=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')fl=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){rt=rt*10+ch-'0';ch=getchar();}
return rt*fl;
}
int cnt=0;
struct str{
string ca;
str(){
}
str(string _bu){
this->ca=_bu;
}
bool operator < (str b)const{
cnt++;
return this->ca < b.ca;
}
};
str s[10000000];
int n;
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
n = read();
for(int i=1;i<=n;i++){
// int a = read();
string a;
cin>>a;
s[i] = str(a);
}
sort(s + 1,s + n);
cout<<cnt<<endl<<clock();
return 0;
}
merge
#include<bits/stdc++.h>
using namespace std;
int read(){
int rt=0,fl=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')fl=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){rt=rt*10+ch-'0';ch=getchar();}
return rt*fl;
}
int cnt=0,n;
struct str{
string ca;
str(){
}
str(string _bu){
this->ca=_bu;
}
bool operator < (str b)const{
cnt++;
return this->ca < b.ca;
}
};
str s[10000000],buf[10000000];
void init(){
n = read();
for(int i = 1;i <= n;i++){
// int a = read();
string a;
cin>>a;
s[i] = str(a);
}
}
void sort(int l,int r){
if(l==r)return;
int mid = l + r >> 1 ,L = l,R = mid+1;
sort(l,mid);sort(mid+1,r);
for(int i = l;i <= r;i++){
if(L<=mid&&R<=r){
if(s[L]<s[R]){
buf[i]=s[L++];
}else{
buf[i]=s[R++];
}
}else if(L<=mid){
buf[i]=s[L++];
}else{
buf[i]=s[R++];
}
}
memcpy(s+l,buf+l,(r-l+1)*sizeof(str));
}
int main(){
freopen("1.in","r",stdin);
freopen("2.out","w",stdout);
init();
sort(1,n);
cout<<cnt<<endl<<clock();
return 0;
}
手写快排
#include<ctime>
#include<cstdio>
#include<iostream>
using namespace std;
int read(){
int rt=0,fl=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')fl=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){rt=rt*10+ch-'0';ch=getchar();}
return rt*fl;
}
int cnt=0,n;
struct str{
string ca;
str(){
}
str(string _bu){
this->ca=_bu;
}
bool operator < (str b)const{
cnt++;
return this->ca < b.ca;
}
bool operator > (str b)const{
cnt++;
return this->ca > b.ca;
}
};
str a[10000000],buf[10000000];
void init(){
n = read();
for(int i = 0;i <= n;i++){
// int aa = read();
string aa;
cin>>aa;
a[i] = str(aa);
}
}
void quicksort(int left,int right)
{
int i,j;str base;
i=left; j=right;
base=a[(i+j)/2];
while (i<=j){
while (a[i]<base) i++;
while (a[j]>base) j--;
if (i<=j){
str t=a[i]; a[i]=a[j];a[j]=t;
i++;
j--;
}
}
if (left<j) quicksort(left,j);
if (i<right) quicksort(i,right);
}
int main()
{
freopen("1.in","r",stdin);
freopen("3.out","w",stdout);
init();
quicksort(0,n-1);
cout<<cnt<<endl<<clock();
return 0;
}
结果如下,不开O2的情况下,归并速度比stl快了100ms
开O2的情况下,还是归并优于快排(两次数据不一样大)
纵观以上的结果,我们还是要根据具体情况选择好的排序方法,当然在OI中这显得不是太重要,但在实际工程应用中,还是要把握好每一种排序方式的优点,进而选择最合适的排序方法。