(图片来自网络)
1.选择排序
时间复杂度:O(n2)
空间复杂度:O(1)
稳定性:不稳定
最容易想到的一种排序
每次选出最值放到数组前端
Code:
//可以直接写在主程序里
for(i=1;i<=n;i++) {
Min=INF; p=0;
for(j=i;j<=n;j++) {
if(a[j]<Min) {
Min=a[j];
p=j;
}
}
swap(a[i],a[p]);
}
2.冒泡排序
时间复杂度:O(n2)
空间复杂度:O(1) //只需要一个用于交换的辅助空间
稳定性:稳定
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
Code:
for(i=1;i<=n-1;i++) {
for(j=1;j<=n-i;j++) {
if(a[j+1]<a[j])
swap(a[j],a[j+1]);
}
}
3.插入排序
时间复杂度:O(n2)
空间复杂度:O(1) //只需要一个用于交换的辅助空间
稳定性:稳定
每次将一个新元素插入一个有序的序列
Code:
for(i=1;i<=n;i++) {
scanf("%d",&a[i]);
j=i;
while(j>1&&a[j]<a[j-1])
swap(a[j],a[j-1]),j--;
}
4.归并排序
时间复杂度:O(nlogn)
空间复杂度:O(n)
稳定性:稳定
运用分治的思想
每次将两个已经有序的序列合并
Code:
const int N=1e5+5;
int a[N],tmp[N];
void Mersort(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1;
Mersort(l,mid);
Mersort(mid+1,r);
int i=l,j=mid+1;
int cnt=l-1;
while(i<=mid&&j<=r)
{
if(a[i]<a[j])
tmp[++cnt]=a[i],i++;
else tmp[++cnt]=a[j],j++;
}
while(i<=mid) tmp[++cnt]=a[i],i++;
while(j<=r) tmp[++cnt]=a[j],j++;
for(i=l;i<=r;i++)
a[i]=tmp[i];
return;
}
5.快排
时间复杂度:O(nlogn)
空间复杂度:O(logn)
稳定性:不稳定
同样运用分治的思想
用数列中间的数将数列分成两半
Code:
void qsort(int l,int r)
{
if(l>=r) return;
int mid=a[(l+r)>>1];
int 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--;
}
}
qsort(l,j);
qsort(i,r);
return;
}
6.STL sort
时间复杂度:O(nlogn)
空间复杂度:O(logn)
稳定性:不稳定
类似快排的排法
Code:
sort(a+1,a+n+1);
需要头文件
#include<algorithm>
可以接受一个参数;
7.堆排序
时间复杂度:O(nlogn)
空间复杂度:O(1)
稳定性:不稳定
堆可以维护一个最值
每次取出最值就可以了
Code:
手写堆
const int N=4e5+5;
typedef int htp;
htp h[N];
int cnt;
int n;
void push(htp x)
{
int now,next;
h[++cnt]=x;
now=cnt;
while(now>1) {
next=now>>1;
if(h[now]<h[next]) //小根堆
swap(h[now],h[next]),now=next;
else break;
}
return;
}
htp top()
{
return h[1];
}
void pop()
{
int now,next;
h[1]=h[cnt];
h[cnt]=0;
cnt--;
now=1;
while(now<=cnt) {
next=now<<1;
if(h[next|1]<h[next]&&(next|1)<=cnt)
next=next|1;
if(next>cnt) break;
if(h[next]<h[now])
swap(h[next],h[now]),now=next;
else break;
}
return;
}
int size()
{
return cnt;
}
bool empty()
{
return (cnt==0) ? true : false;
}
主函数
for(i=1;i<=n;i++) {
scanf("%d",&x);
push(x);
}
for(i=1;i<=n;i++) {
printf("%d ",top());
pop();
}
Code:
STL堆
typedef int htp;
struct cmp
{
bool operator()(const htp &a,const htp &b)
{
return a>b;
}
};
priority_queue<htp,vector<htp>,cmp> q;
//priority_queue<htp,vector<htp>,greater<htp> >
for(i=1;i<=n;i++) {
scanf("%d",&x);
q.push(x);
}
for(i=1;i<=n;i++) {
printf("%d ",q.top());
q.pop();
}
8.桶排序
时间复杂度:O(n+k)
空间复杂度:O(n+k)
稳定性:稳定
Code:
for(i=1;i<=n;i++) {
scanf("%d",&x);
a[x]++;
}
for(i=0;i<=N;i++)
for(j=1;j<=a[i];j++)
printf("%d ",i);
9.map桶排序
时间复杂度:O(nlogn)
空间复杂度:O(1)
稳定性:稳定
可以用map优化桶排序的空间复杂度
但也提高了其时间复杂度
Code:
map<int,int> a;
for(i=1;i<=n;i++) {
scanf("%d",&x);
a[x]++;
}
for(map<int,int>::iterator sit=a.begin();sit!=a.end();sit++)
for(j=1;j<=sit->second;j++)
printf("%d ",sit->first);
10.希尔排序
。。。