多种排序算法的效率观察
注:时间的单位为毫秒,每个数据均观测三次取平均值(排除异常数据)。
时间复杂度较大的排序算法#
随机数据耗时#
数据规模 | 选择排序 | 冒泡排序 | 插入排序 | 猴子排序 |
---|---|---|---|---|
0 | 0 | 0 | 178 | |
0 | 0 | 0 | - | |
0 | 0 | 0 | - | |
130 | 124 | 24 | - |
分析#
选择排序、冒泡排序、插入排序时间复杂度均为
顺序数据耗时#
数据规模 | 选择排序 | 冒泡排序 | 插入排序 |
---|---|---|---|
35 | 0 | 0 |
由于冒泡排序和插入排序当检测到序列已经升序时,可以直接停止算法,使得二者在第一次循环结束时就结束了。选择排序仅仅是比较了
逆序数据耗时#
数据规模 | 选择排序 | 冒泡排序 | 插入排序 |
---|---|---|---|
40 | 79 | 52 |
选择排序竟然反杀了冒泡和插入。也许 c++ 会这点代码给优化了,于是用C语言重新写了一遍,发现有:
数据规模 | 选择排序 | 冒泡排序 | 插入排序 |
---|---|---|---|
163 | 165 | 96 |
这符合之前的规律。但是为什么逆序时c++会出现反常还有待讨论。
时间复杂度较小的排序算法#
耗时#
数据规模 | 归并排序 | 堆排序 | 快速排序 | 快速排序(std) |
---|---|---|---|---|
0 | 0 | 0 | 0 | |
0 | 1 | 0 | 0 | |
12 | 12 | 8 | 5 | |
136 | 176 | 121 | 84 | |
1703 | 2926 | 1397 | 904 |
这些算法复杂度均为
顺序数据耗时#
数据规模 | 归并排序 | 堆排序 | 快速排序 | 快速排序(std) |
---|---|---|---|---|
4 | 10 | 3 | 1 | |
53 | 116 | 40 | 12 | |
634 | 1297 | 491 | 176 |
逆序数据耗时#
数据规模 | 归并排序 | 堆排序 | 快速排序 | 快速排序(std) |
---|---|---|---|---|
4 | 7 | 3 | 1 | |
47 | 98 | 40 | 10 | |
583 | 1048 | 501 | 129 |
我们可以发现,当数据有序时排序的速度比乱序时快。但是逆序时部分算法比顺序时快一点(目前并没有搞明白是为什么)。
复杂度与值域相关的排序算法#
耗时#
数据规模 | 值域 | 桶排序 | 基数排序 |
---|---|---|---|
0 | 0 | ||
54 | 0 | ||
0 | 2 | ||
57 | 4 | ||
2 | 19 | ||
86 | 41 | ||
23 | 254 | ||
344 | 483 |
由于开
相关代码#
选择排序#
#include<bits/stdc++.h>
using namespace std;
int n;
int a[100010];
mt19937 mt(123456);
void xzsort()
{
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(a[i]>a[j])
swap(a[i],a[j]);
}
int main()
{
n=10000;
for(int i=1;i<=n;++i)
a[i]=mt()%1000000000ll;
// sort(a+1,a+1+n);
// reverse(a+1,a+1+n);
int abc=clock();
xzsort();
cout<<clock()-abc<<'\n';
}
冒泡排序#
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int n;
int a[10010];
mt19937 mt(123456);
void mpsort()
{
for(int i=1;i<=n;i++){
bool flag=0;
for(int j=1;j<=n-i;j++)
if(a[j]>a[j+1])
swap(a[j+1],a[j]),flag=1;
if(!flag)break;
}
}
int main()
{
n=10000;
for(int i=1;i<=n;++i)
a[i]=mt()%1000000000ll;
sort(a+1,a+1+n);
reverse(a+1,a+1+n);
int abc=clock();
mpsort();
cout<<clock()-abc<<'\n';
}
插入排序#
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int n;
LL a[10010],b[10010];
mt19937 mt(123456);
void mpsort()
{
for(int i=1;i<=n;i++){
b[i]=a[i];
for(int j=i;j>1;j--)
if(a[j]<a[j-1])
swap(a[j],a[j-1]);
else break;
}
memcpy(a,b,sizeof(LL)*(n+3));
}
int main()
{
n=10000;
for(int i=1;i<=n;++i)
a[i]=mt()%1000000000ll;
sort(a+1,a+1+n);
reverse(a+1,a+1+n);
int abc=clock();
mpsort();
cout<<clock()-abc<<'\n';
}
归并排序#
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int n;
LL a[10000010],b[10000010];
mt19937 mt(123456);
void mergesort(int L,int R)
{
if(L==R)return;
int M=(L+R)>>1;
mergesort(L,M);
mergesort(M+1,R);
int Lp=L,Rp=M+1,pos=L;
while(Lp<=M||Rp<=R){
if((a[Lp]<=a[Rp]&&Lp<=M)||Rp>R)
b[pos++]=a[Lp++];
else b[pos++]=a[Rp++];
}
memcpy(a+L,b+L,sizeof(LL)*(R-L+1));
}
int main()
{
n=10000000;
for(int i=1;i<=n;++i)
a[i]=mt()%1000000000ll;
sort(a+1,a+1+n);
reverse(a+1,a+1+n);
int abc=clock();
mergesort(1,n);
cout<<clock()-abc<<'\n';
}
堆排序#
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int n;
LL a[10000010],DUI[10000010],NUM;
mt19937 mt(123456);
void UP(int x)
{
while(x>1){
if(DUI[x]<=DUI[x>>1])return;
DUI[x]^=DUI[x>>1]^=DUI[x]^=DUI[x>>1];
x>>=1;
}
}
void DOWN(int x)
{
int y=x<<1;
while(y<=NUM){
if(y<NUM&&DUI[y+1]>DUI[y])
y++;
if(DUI[x]>=DUI[y])return;
DUI[x]^=DUI[y]^=DUI[x]^=DUI[y];
x=y;y<<=1;
}
}
void ADD(LL x)
{
DUI[++NUM]=x;
UP(NUM);
}
void DEL()
{
DUI[1]=DUI[NUM--];
DOWN(1);
}
void duisort(LL A[],int Len)
{
NUM=0;
for(int i=1;i<=Len;i++)
ADD(A[i]);
for(int i=Len;i;i--)
A[i]=DUI[1],DEL();
}
int main()
{
n=10000000;
for(int i=1;i<=n;++i)
a[i]=mt()%1000000000ll;
sort(a+1,a+1+n);
reverse(a+1,a+1+n);
int abc=clock();
duisort(a,n);
cout<<clock()-abc<<'\n';
}
快速排序#
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int bit[4]={0,16,32,48},U=65535;
LL n,a[10000010],Maxa[10000010],Mina[10000010];
int st[66000];
mt19937 mt(123456);
void qsort(int L,int R)
{
if(L>=R)return;
int M=(L+R)>>1,Lp=0,Rp=0;
LL Max=max(a[M],max(a[L],a[R])),Min=min(a[M],min(a[L],a[R]));
LL temp=a[M]^a[L]^a[R]^Max^Min;
for(int i=L;i<=R;i++)
if(a[i]<temp)Mina[++Lp]=a[i];
else if(a[i]>temp)Maxa[++Rp]=a[i];
memcpy(a+L,Mina+1,sizeof(LL)*Lp);
fill(a+L+Lp,a+R-Rp,temp);
memcpy(a+R-Rp+1,Maxa+1,sizeof(LL)*Rp);
qsort(L,L+Lp-1);
qsort(R-Rp+1,R);
}
int main()
{
n=10000000;
for(int i=1;i<=n;++i)
a[i]=mt()%1000000000ll;
sort(a+1,a+1+n);
reverse(a+1,a+1+n);
int abc=clock();
qsort(1,n);
cout<<clock()-abc<<'\n';
}
快速排序std#
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int n;
LL a[10000010];
mt19937 mt(123456);
int main()
{
n=10000000;
for(int i=1;i<=n;++i)
a[i]=mt()%1000000000ll;
sort(a+1,a+1+n);
reverse(a+1,a+1+n);
int abc=clock();
sort(a+1,a+1+n);
cout<<clock()-abc<<'\n';
}
基数排序#
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int bit[4]={0,16,32,48},U=65535;
LL n,a[10000010],b[10000010];
int st[66000];
mt19937 mt(123456);
void radixsort()
{
for(int d=0;d<2;++d){
memset(st,0,sizeof st);
for(int i=1;i<=n;++st[(a[i++]>>bit[d])&U]);
for(int i=1;i<=U;++i)st[i]+=st[i-1];
for(int i=n;i>0;--i)b[st[(a[i]>>bit[d])&U]--]=a[i];
memcpy(a,b,sizeof(LL)*(n+5));
}
}
int main()
{
n=1000000;
for(int i=1;i<=n;++i)
a[i]=mt()%10000ll;
int abc=clock();
radixsort();
cout<<clock()-abc<<'\n';
}
桶排序#
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL n,a[10000010],c[10000010];
LL b[10000010];
int st[66000];
mt19937 mt(123456);
void tongsort()
{
for(int i=1;i<=n;++b[a[i++]]);
for(int i=n=0;i<=10000;i++)
while(b[i]--)a[++n]=i;
}
int main()
{
n=100000;
for(int i=1;i<=n;++i)
a[i]=mt()%10000;
int abc=clock();
tongsort();
cout<<clock()-abc<<'\n';
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!