o(n2)的排序
以下三种排序比较好的是插入排序
插入排序
思想:设前i个元素已经有序,然后把第i+1个元素插到合适的位置上
void ins_sort()
{
for(int i=2;i<=n;i++)
{
a[0]=a[i];
//先记住这个数的大小,因为他马上要被替换,且a[0]充当比较的终点.
for(int j=i-1;j>=a[0];j--)//如果比要插入得数大,就要整体往后移动
a[j+1]=a[j];
a[j+1]=a[0];
}
}
选择排序
思想:处理第i个元素时,找到他后面数的最小值.如果这个最小值比他小,就相互交换
void swap_sort(int start,int end)
{
for(int i=start;i<end;i++)
for(int j=i+1;j<end;j++)
if(a[i]>a[j])
swap(a[i],b[i]);
}
冒泡排序
void bubble_sort(int start,int end)]
{
for(int i=start;i<end;i++)
for(int j=end;j>i;j--)//从start到i,在"冒泡"过程中,元素已经排好序
if(a[j-1]>a[j])
swap(a[j],a[j-1]);
}
o(nlogn)的排序
快速排序
快速排序俗称"快排",是基于比较排序中比较快的一种算法.可以去网上搜索快苏排序的视频来加深理解,这是典型的分治的思想.
void quicksort(int start,int end)
{
int low=start,heigh=end;
int temp,check=a[(start+end)/2];
//check有时候选择一个从start到end的随机数
//划分:把check小的数据放到他的左边,吧check大的数放到他的右边.
while(low<=high)
{
while(a[low]<check&&low<=high) low++;
while(a[high]>check&&low<=high) high--;
if(low<=high)
{
swap(a[low],a[high]);
low++;high--;//这两句很关键
}
}
//递归:对已经划分好的两部分分别进行快速排序
if(high>start) quicksort(start,end);
if(low<end) quicksort(low,end);
}
归并排序
void merge(int low,int mid,int high)
{
int n=high-low+1;
int i=low,end1=mid;
int j=mid+1,end2=high;
int k=0;
while(i<=end1&&j<=end2)
{
//将array[i]和array[j]中最小的这个赋给temp[k]
if(array[i]<=array[j]) temp[k]=array[i++];
else temp[k]=array[j++];
k++;
}
while(i<=end1) temp[k++]=array[i++];
while(j<=end2) temp[k++]=array[j++];
for(int x=0;x<k;x++)
array[low+x]=temp[x];
}
void merge_sort(int low,int high)//分开解决
{
if(low<high)
{
int mid=low+(hight-low)>>1;//二分
//递归分治
merge_sort(low,mid);
merge_sort(mid+1,high);
merge(low,mid,high);//二路归并
}
}
堆排序
思想:用对的特性来完成排序
实现过程:
1.将数组转化成一个堆(使用buildheap完成).
2将堆顶的最大元素取出(removemax),并把它放到数组最后(准确的说,位置是对中的元素减1).
3.剩余的重新排列.
4.重复2,直到堆为空.
堆排序相比其他o(nlogn)的排序算法要慢很多,适合寻找第k大(小)的元素
o(n)的排序
桶排序
思想:设计n个桶,根据元素本身进行分配.因为m个桶是按顺序排列的,所以分配元素之后元素也会按照顺序排列,(n<=1e6)
int cnt[M+10];
memset(cnt,0,sizeof(cnt));//在cstring库中,将数组整体赋值为0.
for(int i=0;i<N;i++)
cnt[a[i]]++;
//从cnt[0]开始枚举就行了.例如
for(int i=0;i<M;i++)
while((cnt[i]--)>0)
cout<<i<<' ';
STL库中的排序
原型:
void sort<_Ranlt>(const_Ranlt_first,const_Ranlt_last);
这个排序是o(nlogn)的,会经常用到,相比其他o(nlogn)的排序代码简洁了不少,因为里面自带有好多种排序.
void stl_sort(int end)
{
sort(a+1,a+end+1);
}
总结
算法比较:
1.稳定性
插入排序,冒泡排序,归并排序其他线性的排序是稳定的.
选择排序,快速排序等是不稳定的.
2.时间复杂度
前面标题上说了
3.辅助空间
线性时间排序,归并排序的辅助空间为o(n).
其他的排序为o(1);
4.其他方面
插入,冒泡排序速度较慢,但待排序的队列基本有序时,这种排序能达到较快的速度.在这种情况下,快速排序反而慢了.
当n较小时,对稳定性不作要求时宜用选择排序,对稳定性有要求时宜用插入或冒泡排序.若待排序的记录的关键字在一个明显有范围内时,若空间允许用桶排序
当n较大时,关键字元素比较随机,对稳定性没有要求时宜用快速排序.
当n较大时,关键字元素可能出现本身是有序的,对稳定性有要求时,空间允许的情况下,宜用归并排序.
当n较大时,关键字元素可能出现本身是有序的,对稳定性没有要求时宜用堆排序