排序
题目链接
P1177 【模板】快速排序
快速排序
- 时间复杂度:\(O(nlogn)\)
- 空间复杂度:\(O(1)\)
#include<bits/stdc++.h>
using namespace std;
void quick_sort(int a[],int l,int r)
{
if(l>=r)return ;
int i=l-1,j=r+1,x=a[l+r>>1];
while(i<j)
{
do i++;while(a[i]<x);
do j--;while(a[j]>x);
if(i<j)swap(a[i],a[j]);
}
quick_sort(a,l,j),quick_sort(a,j+1,r);
}
int n,a[1000005];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
quick_sort(a,1,n);
for(int i=1;i<=n;i++)printf("%d ",a[i]);
return 0;
}
快速选择
链接:786. 第k个数
- 时间复杂度:\(O(n)\)
- 空间复杂度:\(O(1)\)
#include<bits/stdc++.h>
using namespace std;
int a[100005],n,k;
int quick_sort(int a[],int l,int r,int k)
{
if(l==r)return a[k];
int i=l-1,j=r+1,x=a[l+r>>1];
while(i<j)
{
do i++;while(a[i]<x);
do j--;while(a[j]>x);
if(i<j)swap(a[i],a[j]);
}
if(k<=j)return quick_sort(a,l,j,k);
return quick_sort(a,j+1,r,k);
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
printf("%d",quick_sort(a,1,n,k));
return 0;
}
归并排序
- 时间复杂度:\(O(nlogn)\)
- 空间复杂度:\(O(n)\)
#include<bits/stdc++.h>
using namespace std;
int n,a[1000005],tmp[1000005];
void merge_sort(int a[],int l,int r)
{
if(l>=r)return ;
int mid=l+r>>1;
merge_sort(a,l,mid),merge_sort(a,mid+1,r);
int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r)
if(a[i]<a[j])tmp[k++]=a[i++];
else
tmp[k++]=a[j++];
while(i<=mid)tmp[k++]=a[i++];
while(j<=r)tmp[k++]=a[j++];
for(int i=l,j=0;i<=r;i++,j++)a[i]=tmp[j];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
merge_sort(a,1,n);
for(int i=1;i<=n;i++)printf("%d ",a[i]);
return 0;
}
逆序对的数量
链接:788. 逆序对的数量
- 时间复杂度:\(O(nlogn)\)
- 空间复杂度:\(O(n)\)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
using LL=long long;
int n,a[N],t[N];
LL merge_sort(int a[],int l,int r)
{
if(l>=r)return 0;
int mid=l+r>>1;
LL res=merge_sort(a,l,mid)+merge_sort(a,mid+1,r);
int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r)
{
if(a[i]<=a[j])t[k++]=a[i++];
else
res+=mid-i+1,t[k++]=a[j++];
}
while(i<=mid)t[k++]=a[i++];
while(j<=r)t[k++]=a[j++];
for(int i=l,j=0;i<=r;i++,j++)a[i]=t[j];
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
printf("%lld",merge_sort(a,1,n));
return 0;
}
堆排序
- 时间复杂度:\(O(nlogn)\)
- 空间复杂度:\(O(1)\)
#include<bits/stdc++.h>
using namespace std;
int n,cnt,a[100005];
void down(int u)
{
int t=u;
if(u*2<=cnt&&a[t]>a[u*2])t=u*2;
if(u*2+1<=cnt&&a[t]>a[u*2+1])t=u*2+1;
if(u!=t)
{
swap(a[t],a[u]);
down(t);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
cnt=n;
for(int i=n/2;i;i--)down(i);
for(int i=1;i<=n;i++)
{
printf("%d%c",a[1],i<n?' ':'\0');
a[1]=a[cnt--];
down(1);
}
return 0;
}
模拟堆
链接:839. 模拟堆
操作 | |
---|---|
1 | 插入一个数 \(x\) |
2 | 输出最小值 |
3 | 删除最小值 |
4 | 删除第 \(k\) 个插入的数 |
5 | 修改第 \(k\) 个插入的数,将其变为 \(x\) |
- 时间复杂度:\(O(nlogn)\)
- 空间复杂度:\(O(n)\)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,cnt,k,x;
int h[N],hp[N],ph[N];
void heap_swap(int a,int b)
{
swap(ph[hp[a]],ph[hp[b]]);
swap(hp[a],hp[b]);
swap(h[a],h[b]);
}
void down(int u)
{
int t=u;
if(2*u<=cnt&&h[t]>h[2*u])t=2*u;
if(2*u+1<=cnt&&h[t]>h[2*u+1])t=2*u+1;
if(u!=t)
{
heap_swap(u,t);
down(t);
}
}
void up(int u)
{
if(u/2>=1&&h[u]<h[u/2])
{
heap_swap(u,u/2);
up(u/2);
}
}
int main()
{
scanf("%d",&n);
while(n--)
{
char op[5];
scanf("%s",op);
if(!strcmp(op,"I"))
{
scanf("%d",&x);
h[++cnt]=x;
m++;
ph[m]=cnt,hp[cnt]=m;
up(cnt);
}
else if(!strcmp(op,"PM"))
printf("%d\n",h[1]);
else if(!strcmp(op,"DM"))
{
heap_swap(1,cnt--);
down(1);
}
else if(!strcmp(op,"D"))
{
scanf("%d",&k);
k=ph[k];
heap_swap(k,cnt--);
down(k),up(k);
}
else
{
scanf("%d%d",&k,&x);
k=ph[k];
h[k]=x;
down(k),up(k);
}
}
return 0;
}
基数排序
设\({\displaystyle n}\)是排序元素个数,\({\displaystyle k}\)是数字位数
- 时间复杂度:\(O(kn)\)
- 空间复杂度:\(O(n+k)\)
#include<bits/stdc++.h>
using namespace std;
int a[100005],tmp[100005],cnt[10],n;
int max_bit(int a[],int n)
{
int d=1,p=10;
for(int i=1;i<=n;i++)
while(a[i]>=p)
{
d++;
p*=10;
}
return d;
}
void radix_sort(int a[],int n)
{
int d=max_bit(a,n);
int radix=1;
for(int i=1;i<=d;i++)
{
memset(cnt,0,sizeof cnt);
for(int j=1;j<=n;j++)cnt[(a[j]/radix)%10]++;
for(int j=1;j<10;j++)cnt[j]=cnt[j]+cnt[j-1];
for(int j=n;j;j--)
{
int k=(a[j]/radix)%10;
tmp[cnt[k]]=a[j];
cnt[k]--;
}
memcpy(a,tmp,sizeof tmp);
radix*=10;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
radix_sort(a,n);
for(int i=1;i<=n;i++)printf("%d ",a[i]);
return 0;
}
桶排序
这里的c++
实现与最优有些出入~
- 时间复杂度:\(O(n+k)\)
- 空间复杂度:\(O(n+k)\)
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> a;
void bucket_sort(vector<int> &a)
{
int mx=a[0],mn=a[0];
for(int &i:a)mx=max(mx,i),mn=min(mn,i);
int d=mx-mn;
int bucket_num=a.size();
if(bucket_num==1)return ;
vector<list<int>> lst(bucket_num);
for(int &i:a)
{
int idx=(i-mn)/(d/(bucket_num-1));
lst[idx].push_back(i);
}
a.clear();
for(auto &bucket:lst)
{
vector<int> t(bucket.begin(),bucket.end());
sort(t.begin(),t.end());
a.insert(a.end(),t.begin(),t.end());
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
a.push_back(x);
}
bucket_sort(a);
for(int &i:a)printf("%d ",i);
return 0;
}