排序
1.归并
2.快排
1.归并排序
归并排序将一组数分成两部分,从这两部分选最小的数到另外的数组中
如:6 2 4 3 5 1
分后:
6 2 4->...->2 4 6
3 5 1->...->1 3 5
接着分别取1 2 3 4 5 6放到另外的数组中
归并排序时间复杂度O(nlogn)最坏情况下归并排序影响不大(兄弟,稳!)
void guisort(int l,int r){
if(l==r) return ;
int mid=(l+r)/2;
guisort(l,mid);
guisort(mid+1,r);
int p=l,q=l,k=mid+1; //p左区间指针 k为右区间指针 q为新数组指针
while(p<=mid&&k<=r){
if(a[p]<=a[k]) b[q++]=a[p++]; //复制左边数据
//即 b[q]=a[p],q++,p++;
else b[q++]=a[k++]; //复制右边数据
}
while(p<=mid) b[q++]=a[p++]; //左边可能有剩余
while(k<=r) b[q++]=a[k++]; //右边也可能有剩余
for(int i=l;i<=r;i++) a[i]=b[i];//复制回去
}
2.快排:
选取一个随机数,将小于这个随机数的数放到这个数的左边,大于这个数的数放到这个随机数的右边,从分成的区间里面再进行重复操作快速排序辅助空间O(log2 n),平均时间复杂度O(nlogn)最坏情况O(n^2).
void Quick_sort(int a[],int l,int r){//快排
if(l >= r) return ;
int mid = a[rand()%(r-l+1)+l];
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--;
}
Quick_sort(a,l,j);
Quick_sort(a,i,r);
}
- 注意mid要保存a数组的某个值
如果写成:
mid = l + r >> 1;
...
while(a[i] < a[mid]) i++;
是错误的,因为在排序的时候mid的值是固定的但是 a[mid] 可能会互换导致基准数改变
//快排的其他写法
void Quick_sort(int a[],int l,int r){
if(l>=r) return ;//可能是空区间
int falg=a[rand()%(r-l+1)+l];
int p=l,q=r;
for(int i=l;i<=r;i++){
if(a[i]<falg) b[p++]=a[i];
if(a[i]>falg) b[q--]=a[i];
}
//现在t[l,p-1] 全是比falg小的 t[p+1,r] 全是比falg大的 再复制 b 的值到a 递归 排序
for(int i=l;i<p;i++) a[i]=b[i];
for(int i=r;i>q;i--) a[i]=b[i];
for(int i=p;i<=q;i++) a[i]=falg;
quicksort(a,l,p-1);
quicksort(a,p+1,r); //[p,q]是falg不用排序
}
void Quick_sort(int a[],int l,int r){
if(l >= r) return ;
int falg = a[rand()%(r - l + 1) + l] ;
int i = l - 1 , j = r + 1;
while(i <= j){
do i++ ; while(a[i] < falg) ;
do j-- ; while(a[j] > falg) ;
if(i <= j) swap(a[i],a[j]);//此处不用 i++ j--
}
Quick_sort(a,l,j);
Quick_sort(a,j+1,r);
}
对于falg要取a数组的随机一个数,否则容易被卡数据导致超时等问题
注:OI蒻驹一枚,文章仅代表个人观点,如有不对,敬请指出,共同进步,谢谢。

浙公网安备 33010602011771号