重走算法路--快速排序

133 阅读3分钟

题目来源于ACWING

快速排序 23/11/16

习题1——快速排序

给定你一个长度为 n 的整数数列。

请你使用快速排序对这个数列按照从小到大进行排序。

并将排好序的数列按顺序输出。

输入格式

输入共两行,第一行包含整数 n

第二行包含 n 个整数(所有整数均在 1∼109 范围内),表示整个数列。

输出格式

输出共一行,包含 n 个整数,表示排好序的数列。

数据范围

1≤n≤100000

输入样例:

5
3 1 2 4 5

输出样例:

1 2 3 4 5
#include<iostream>
using namespace std;


//多开数组长度,避免边界问题
const int N =100010;
int arr[N];

//总体思路是递归解决问题
//快排的思想:
//你有两个数组,左边数组所有元素均小于右边数组,那么你只需讲两个数组分别排好序,再合并即可
//那对于左右两边数组的该如何排序呢?
//只需递归把左右两边数组分别拆分成更小的数组即可,直到每个数组被拆分到只有一个元素则完成递归,得到结果
void quick_sort(int l,int r){
    if(l>=r)    return ;//递归排序结束

    //关于为啥下面变量不是 i=l ,j=r 需要看下面代码:
    //  while(i<j)
    // {
    //     while(arr[++i]<x) ;
    //     while(arr[--j]>x) ;
    //     if(i<j) swap(arr[i],arr[j]);
    // }
    // 在这里,while循环内部使用了前置递增(++i)和前置递减(--j),因此在每次迭代之前就会先递增i,
    // 递减j,然后再进行比较。由于i和j的初始值,while循环的第一次迭代就能确保i指向数组中第一个
    // 大于等于x的元素,而j指向数组中第一个小于等于x的元素。
    // 这样的初始化方式确保了在进入while循环之前,i和j就能够分别指向数组的两侧,这是为了确保在
    // 排序过程中,i和j能够逐渐靠拢并找到需要交换的元素。
    int i=l-1,j=r+1;
    //取数组中间值作为左右划分依据
    int x = arr[l+r>>1];
    while(i<j)
        {
            while(arr[++i]<x) ;
            while(arr[--j]>x) ;
            if(i<j) swap(arr[i],arr[j]);
        }
    quick_sort(l,j);
    quick_sort(j+1,r);
}


int main(){

    //初始化数组
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)    cin>>arr[i];

    //进行快排
    quick_sort(0,n-1);

    //输出结果
    for(int i=0;i<n;i++)    cout<<arr[i]<<" ";

    return 0;

}

习题2——第k个数

给定一个长度为 n 的整数数列,以及一个整数 k,请用快速选择算法求出数列从小到大排序后的第 k�个数。

输入格式

第一行包含两个整数 n和 k。

第二行包含 n 个整数(所有整数均在 1∼109 范围内),表示整数数列。

输出格式

输出一个整数,表示数列的第 k 小数。

数据范围

1≤n≤100000
1≤k≤n

输入样例:

5 3
2 4 1 5 3

输出样例:

3
#include<iostream>
using namespace std;

const int N=100010;
int arr[N];

//思路仍然是快排的思路,但是本题要求的是第k个元素(从1开始的第k个元素),因此这里需要注意判断临界问题
int quick_sort_k(int l ,int r,int k){
    if(l>=r) return arr[l];
    int x=arr[l+r>>1];
    int i=l-1,j=r+1;
    while(i<j){
        while(arr[++i]<x);
        while(arr[--j]>x);
        if(i<j)    swap(arr[i],arr[j]);
    }
    //因为k是从1开始算的,但是这里数组的实际输入从0开始算,因此此处k-1进行对其
    if(k-1<=j) 
        return quick_sort_k(l,j,k);
    else 
        return quick_sort_k(j+1,r,k);

}


int main(){
    int n,k;
    cin>>n>>k;
    for(int i=0;i<n;i++) cin>>arr[i];
    cout<<quick_sort_k(0,n-1,k);
    return 0;
}