1.快排

1.快排

方法

1.确定分界点(可以是p[0],p[n],p[n/2],随机)

 

2.(重点)调整区间(将<=n的放到左侧,把>=n的放到右侧)分成两部分

用两个指针分别指两端,先后向中间靠拢

 

 

 

3.递归处理左右两边。

(不稳定)

可以想办法让每个数不一样:比如把里面的元素变成二元组a=><a,i>。

代码

1.暴力

//用空间换时间,多开两个数组
int a[n];
int b[n];
int p[2*n];//排p序
int n1=0,n2=0;
for (int i=0;i<=2*n;i++)
{
    if(p[i]>=p[0])
    {
        a[n1++]=p[i];
    }else if(p[i]<p[0])
    {
        b[n2++]=p[i];
    }
}

 

2.优美而简洁 q[]

#include<iostream>using namespace std;
const int N =1e6+10;
int n;
int q[N];
void quick_sort(int q[],int l,int r)
{
    if(l>=r) return ;//如果数组里只有1个或没有数,直接结束
    //1.int q[r] //2.int q[(l+r+1)/2] (有时候用两边会超时)
    int x=q[l],i=l-1,j=r+1;//因为是先同时向中间靠拢,先把两个指针放在数组外面
    //
    while(i<j)//i不能大于j否则结束
    {
        do i++;while(q[i]<x);//向中间走直到遇到大于x的
        do j--;while(q[j]>x);//向中间走直到遇到小于x的
        if(i<j) swap(q[i],q[j]);//将两个数交换位置,再继续走
    }
    //quick_sort(q,l,i-1)
    //quick_sort(q,i,r)
    quick_sort(q,l,j);//递归
    quick_sort(q,j+1,r);
/*eg:
2
1 2
用i则不能取到左边界,把x取值改成向上取整
用j则不能取到右边界,把x取值改成向下取整
取到边界会导致递归死循环
***************************
以j为划分时,x不能选q[r] (若以i为划分,则x不能选q[l])
假设 x = q[r]
​
关键句子quick_sort(q, l, j), quick_sort(q, j + 1, r);
​
由于j的最小值是l,所以q[j+1..r]不会造成无限划分
​
但q[l..j](即quick_sort(q, l, j))却可能造成无限划分,因为j可能为r
​
举例来说,若x选为q[r],数组中q[l..r-1] < x,
​
那么这一轮循环结束时i = r, j = r,显然会造成无限划分
*/
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&q[i]);
    
    quick_sort(q,0,n-1);
    
    for(int i=0;i<n;i++)printf("%d ",q[i]);
    
    return 0;
}
注意:由于使用do-while循环,所以i和j一定会!!!自增!!!,使得循环会继续下去,但是如果采用while循环(i和j的初始化做出对应的变更),i和j在特殊情况下不自增的话,循环就会卡死
​
例如:
  while(q[i] < x) i++;
  while(q[j] > x) j--;
当q[i]和q[j]都为 x 时, i 和 j 都不会更新,导致 while 陷入死循环

 

 
posted @ 2022-05-16 19:46  scanfppp  阅读(169)  评论(0)    收藏  举报