排序

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数组的随机一个数,否则容易被卡数据导致超时等问题

posted @ 2021-02-02 15:43  Carrot_Rui  阅读(82)  评论(0)    收藏  举报