浅谈排序
浅谈排序
排序
桶排序
基本思想:每读入的数据x,桶a[x]就加一,输出时按桶的顺序,桶里有几个数就输出几次。
缺点:桶的数量取决于数据的大小,那就面临着MLE的问题,比如x在int范围内时,我们就要开2^16个桶,这非常的浪费空间,而且当带排序数据的类型为浮点数是,那就呵呵了,因为桶的标号只能是整数,总的来说,桶排序的使用范围并不广。
实现起来简单粗暴,只要不怕MLE就可以大胆上,时间复杂度真的是没毛病,数据个数n+桶的个数m,常数忽略不计O(m+n)。
来波代码,其实真的简单。
#include<bits/stdc++.h> using namespace std; int a[11010],n,x,maxn=-1; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&x); ++a[x]; maxn=max(maxn,x); } for(int i=1;i<=maxn;i++) while(a[i]--) printf("%d ",i); return 0; }
冒泡排序
基本思想:每次比较两个相邻的元素,如果他们的顺序错误就把他们交换位置。
缺点:一个字:慢
这个代码的时间复杂度真的令人无语,两重循环,外层跑n-1次冒泡(最坏情况),内层跑1~n-i(后面i-1个数已经拍好),所以时间复杂度O(n^2)。
个人认为,既然有快排的存在,冒泡排序实在没有太多实际用途。
废话不多说,直接上代码。(从小到大)
#include<bits/stdc++.h> using namespace std; int n,a[10020]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<n;i++)//最坏的情况只需跑n-1次 for(int j=1;j<=n-i;j++)//后i-1位一定已排好 if(a[j]>a[j+1]) swap(a[j],a[j+1]); for(int i=1;i<=n;i++) printf("%d ",a[i]); return 0; }
归并排序
基本思想:二分大法,将数列不断二分,直到只剩一个元素为止,然后不断向上归并,归并时已经可以保证两个子数列已经排序完成,所以可以用两个指针分别指向两个子序列的首部,比较将较小的一个放到一个新数组里,然后指针++。
其实c++里有一个merge_sort函数,就是用的归并排序,可以直接调用。
不过话说这归并排序几乎只有两个用途: 一是排序(不如快速排序快),二是求逆序对(需要手写函数),所以总的来说,上文中的merge_sort并没有太多用处。但是思想总是有用的,还是应学习一下。
时间复杂度:O(NlogN)。
贴代码
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int a[1001],b[1001]; int n; void my_gb_sort(int l,int r) { if(l==r) return; int m=(l+r)/2; my_gb_sort(l,m); my_gb_sort(m+1,r); int p1=l,p2=m+1; for (int i=l;i<=r;i++) { if (p1<=m && p2<=r) { if (a[p1]<a[p2]) b[i]=a[p1++]; else b[i]=a[p2++]; } else { if (p1<=m) b[i]=a[p1++]; else b[i]=a[p2++]; } } for(int i=l;i<=r;i++) a[i]=b[i]; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); my_gb_sort(1,n); for(int i=1;i<=n;i++) printf("%d ",a[i]); return 0; }
快速排序
sort大法好!!
咳咳,回正题,快速排序是一种基于二分思想的算法:每次随机选择一个序列中的数字temp作为基准点,然后以它为基准将比它小的数字放到他的左边,把比他大的放到他的右边然后再对他两侧的序列做相同的操作。
具体的操作是用两个指针对序列进行扫描实现的,i指针从左向右扫描,j指针从右向左扫描,直到i遇到比temp大的数,j遇到比temp小的数或i=j是停止。然后将两个数字交换。
快速排序的时间复杂度最差为0(n^2),但它的平均复杂度为O(nlogn),是最常用的排序算法。
#include<bits/stdc++.h> using namespace std; int n,a[20010]; void qsort(int l,int r) { if(l>r) return; int temp=a[l]; int i=l,j=r; while(i!=j) { while(a[j]>=temp&&i<j) --j; while(a[i]<=temp&&i<j) ++i; if(i<j) swap(a[i],a[j]); } a[l]=a[i]; a[i]=temp; qsort(l,i-1); qsort(i+1,r); return; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); qsort(1,n); for(int i=1;i<=n;i++) printf("%d ",a[i]); return 0; }
关于排序我就说这些,等我成长为神犇,再回来补充吧。