快速排序模板及快速选择例题
快速排序模板及快速选择例题
快速排序
思路
-
首先选择出分界值,x = q[l]或q[r]或 q[(l +r) / 2];
-
将整个数组分为左右两段,使得左边的所有数都 <= x,右边的所有数都 >= x
2.1 将两个指针i, j分别指向数组的两端, 即i = l - 1; j = r + 1;
2.2 先将i指针向右移动,如果q[i]的值<x,则i继续移动;如果q[i]的值 >= x ,则停止移动;
2.3 将j指针向左移动,如果q[j]的值>x,则i继续移动;如果q[j]的值 <= x ,则停止移动;
2.4 当两个指针都停止时,则两个指针的值互换位置;
2.5然后继续重复2.2,2.3,2.4 直至i指针与j指针重合,或者i指针到了j指针的右边,停止移动
-
最后分别递归左右两个数组。
代码如下:
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int n;
int q[N];
void kuaipai(int q[], int l, int r){
if(l >= r) return;
int i = l - 1, j = r + 1, x = q[(l + r) / 2];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
kuaipai(q, l, j);
kuaipai(q, j + 1, r);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
kuaipai(q, 0, n - 1);
for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);
return 0;
}
快速选择排序
给定一个长度为 nn 的整数数列,以及一个整数 kk,请用快速选择算法求出数列从小到大排序后的第 kk 个数。
输入格式
第一行包含两个整数 nn 和 kk。
第二行包含 nn 个整数(所有整数均在 1∼1091∼109 范围内),表示整数数列。
输出格式
输出一个整数,表示数列的第 kk 小数。
数据范围
1≤n≤1000001≤n≤100000,
1≤k≤n1≤k≤n
输入样例:
5 3
2 4 1 5 3
输出样例:
3
解题思路:
- 首先将该数列进行快速排序
- 然后判断左边的个数left与k的大小
- 如果left大于k 则直接输出第k个值
- 如果left小于k ,则输出k - left
代码如下
#include <iostream>
using namespace std;
const int N = 100010;
int n, k;
int q[N];
int kuaixuan(int q[], int l, int r, int k){
if(l == r) return q[l];
int x = q[(l + r) / 2], i = l -1, j = r + 1;
while(i < j){
do i ++; while(q[i] < x);
do j --; while(q[j] > x);
if(i < j) swap(q[i], q[j]);
}
int sl = j - l + 1;
if(k <= sl) return kuaixuan(q, l, j , k);
else return kuaixuan(q, j + 1, r, k - sl);
}
int main(){
int n, k;
scanf("%d%d", &n, &k);
for(int i = 0; i < n; i++) scanf("%d", &q[i]);
cout << kuaixuan(q, 0, n - 1, k) << endl;
return 0;
}