基于比较的排序
冒泡排序
元素相邻位置互相交换
选择排序
每次查找为排过序的元素中最小的位置
插入排序
把当前位置的元素插入到已经排过序的元素中去,使其有序
希尔排序
分段进行插入排序
快速排序
分治处理 把每个元素放进她应该在的位置上
应用
静态选择第k大
归并排序
分治处理并进行合并
应用
求逆序数点击打开poj题目链接
#include<cstdio>
#define N 600050
using namespace std;
long long p[N],a[N];
long long sum=0;
void merge(int first,int last)
{
int mid=(first+last)/2;
int i1=0,i2=first,i3=mid+1;
while(i2<=mid&&i3<=last)
{
if(a[i2]>a[i3])
{
p[i1++]=a[i3++];
sum+=mid+1-i2;
}
else p[i1++]=a[i2++];
}
while(i2<=mid)p[i1++]=a[i2++];
while(i3<=last)p[i1++]=a[i3++];
i1=first;i2=0;
while(i2<last-first+1)a[i1++]=p[i2++];
}
void merge_sort(int first,int last)
{
int mid;
if(first<last)
{
mid=(first+last)/2;
merge_sort(first,mid);
merge_sort(mid+1,last);
merge(first,last);
}
}
int main()
{
int n;
while(scanf("%d",&n),n)
{
for(int i=0;i<n;i++)
{
scanf("%lld",&a[i]);
p[i]=a[i];
}
sum=0;
merge_sort(0,n-1);
printf("%lld\n",sum);
}
return 0;
}
堆排序
用堆维护,进行选择排序
应用
问题描述
给定各包含n个数两个数列A、B,分别从A和B中任意取一个数相加得到和,这样会有n^2种结果(包括重复的),求n^2个结果中前n个最小的和。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010
using namespace std;
int f[N],s[N], val1[N], val2[N],ans[N], hs,n;
void keep( int rt ) {
int cur = rt;
int l = rt<<1;
int r=l+1;
if( l<=hs && val1[ f[l] ]+ val2[ s[l] ]< val1[ f[cur] ]+ val2[ s[cur] ] ) cur=l;
if( r<=hs && val1[ f[r] ]+ val2[ s[r] ] < val1[ f[cur] ]+ val2[ s[cur] ] ) cur=r;
if( cur != rt ) {
swap(f[cur],f[rt]);
swap(s[cur],s[rt]);
keep(cur);
}
}
int work( int n )
{
hs=n;
for( int i = 0; i < n; i ++ ){
ans[i]= val1[ f[1] ]+val2[ s[1] ];
if( f[1] <n ) f[1]++;
else {
f[1]=f[hs];
s[1]=s[hs--];
}
keep(1);
}
}
int main() {
while( ~scanf("%d",&n) ) {
for( int i = 1; i <= n; i ++ )
scanf("%d",&val1[i]);
for( int i = 1; i <= n; i ++ )
scanf("%d",&val2[i]);
sort(val1+1,val1+n+1);
sort(val2+1,val2+n+1);
for( int i = 1; i <= n; i ++ )
f[s[i]=i]=1;
work(n);
printf("%d",ans[0]);
for( int i = 1; i < n; i ++ )
printf(" %d",ans[i]);
printf("\n");
}
return 0;
}
基于索引的排序
计数排序
根据数据的类型进行映射索引,然后进行索引查找排序
基数排序
把数据进行分割后进行排序
桶排序
根据数据建立映射到某区域里,然后进行分桶处理,同一桶内进行插入排序
外部排序
一般是对相对于较大文件进行排序,文件比较大,内存不足。
一般分为两个过程:
1、把大文件分成多个子文件,并一一排序单个子文件。
2、合并所有的子文件
主要是在合并的过程中,由于内存不足,所以只能边合并边写到文件。这个过程中可以用堆、胜者树或败者树进行维护
网络排序
是针对多处理机并行处理的排序
字符串排序
对于多个字符串,可以先用字典树存储,然后进行先序遍历即可完成排序