快速排序[模板]

快速排序


图

  1. 确定分界点x:

    方法:

    • q[l] //左端点
    • q[r] //右端点
    • q[(l+r)/2] //中点
    • q[随便] //任意

2.调整区间:

图2

把<=x的和>=x的分开(x随意,放两边都可以)


暴力实现:

int a[],int b[];	//a装<=x,b装>=x
memset(a,0x3f3f3f3f,sizeof(a));
memset(b,0x3f3f3f3f,sizeof(b));
for(int i=l;i<=r;i++)
{
    if(q[i]<=q[x]) a[i]=q[i];
    else b[i]=q[i];
}//先分类
while(a[i]!=0x3f3f3f3f)	lena++;
while(b[i]!=0x3f3f3f3f)	lenb++;
for(int i=1;i<=lena;i++) q[i]=a[i];
for(int i=lena+1;i<=lenb;i++) q[i]=b[i];
//再把a[]和b[]放回q[]里去

优美实现:

在这里插入图片描述

用两个指针i,j分别从两端向x的方向移动

当i的其中一个位置>=x时,将i停止移动,开始移动j

当j的其中一个位置<=x时,将j停止移动,将两个值交换

然后继续移动i,重复…直到i与j都到达x处

int i=l;//等于左端点
int j=r;//等于右端点
while(q[i]<=q[x]) i++;//如果i的其中一个位置>=x时,将i停止移动
while(q[j]>=q[x]) j--;当j的其中一个位置<=x时,将j停止移动
swap(q[i],q[j]);//将两个值交换

3.分别处理左右两端(递归)

只用把左右两边分别排好序了,又因为左区间的最大值小于右区间的最小值,所以两边就排好序了。


Ac Code

//运用优美实现完成的代码
#include <iostream>

using namespace std;

const int N=1e6+10;

int n,q[N];

void qsort(int q[],int l,int r)
{
    if(l>=r) return ;
   	//如果两个指针重合就完成了
    
    int x=q[(l+r)/2];//其实在哪都没所谓
    int i=l-1,j=r+1;
    //因为下面的是无论三七二十一都将i,j移动一位,再判断到没到,所以要在边界的两端前一位开始
    while(i<j)
    {
       	do i++;	  while(q[i]<x);//找到第一个不符合规则的点
       	do j--;   while(q[j]>x);//找到第一个不符合规则的点
       	if(i<j)	swap(q[i],q[j]);//交换它们的值
    }
    qsort(q,l,j);//左半序列
    qsort(q,j+1,r);//右半序列
}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&q[i]);
    //输入
    qsort(q,0,n-1);
    //排序
    for(int i=0;i<n;i++) printf("%d ",q[i]);
    //输出
    return 0;
}
原文地址:https://www.cnblogs.com/BorisDimitri/p/13546608.html