快速排序
Method
- 确定分界点x:q[l] or q[r] or q[(l+r)] // 取中间数,也可以取随机数。
- 调整区间范围:左端所有数<=x,右端所有数>=x
- 递归排序left,递归排序right)
Example1:快速排序
给定你一个长度为n的整数数列。
请你使用快速排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。
输入格式
输入共两行,第一行包含整数 n。
第二行包含 n 个整数(所有整数均在1~109109范围内),表示整个数列。
输出格式
输出共一行,包含 n 个整数,表示排好序的数列。
数据范围
1≤n≤1000001≤n≤100000
输入样例:
5
3 1 2 4 5
输出样例:
1 2 3 4 5
#include<iostream>
using namespace std;
const int N = 1000010;
int n;
int q[N];
//快排模版
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;//判断边界,如果输入只有一个数或者没有数 就直接return
int x = q[(l + r) / 2], i = l - 1, j = r + 1;//取分界点x(中间点),i和j是指针
while (i < j)//循环迭代,交换,调整区间
{
do i ++; while (q[i] < x);//循环直到q[i]>x
do j --; while (q[j] > x);//循环直到q[i]<=x
//如果循环之后,指针i和j没有相遇,交换两个数
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j);
quick_sort(q , j + 1, 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;
}
Example2:第k个数
给定一个长度为n的整数数列,以及一个整数k,请用快速选择算法求出数列的第k小的数是多少。
输入格式
第一行包含两个整数 n 和 k。
第二行包含 n 个整数(所有整数均在1~109109范围内),表示整数数列。
输出格式
输出一个整数,表示数列的第k小数。
数据范围
1≤n≤1000001≤n≤100000,
1≤k≤n
输入样例:
5 3
2 4 1 5 3
输出样例:
3
#include <iostream>
using namespace std;
const int N = 100010;
int n,k;
int q[N];
int quick_sort(int q[], int l, int r, int k)
{
if (l == r) return q[l];
int x = q[l + r >> 1], i = l - 1, j = r + 1;
while(i < j)//循环遍历
{
while(q[ ++ i] < x);
while(q[ -- j] > x);
if (i < j) swap(q[i], q[j]);
}
//与快速排序的不同在于,如果k<=sl,只遍递归左边,否则遍历右边。
int sl = j - l + 1;//左边存的数的数量,即j指针的左边 l输入为0
if (k <= sl) return quick_sort(q, l, j, k);//k<=sl,只需要遍历左边
return quick_sort(q, j + 1, r, k - sl);//k>sl,遍历右边区域,并且减去左边区域的数:k-sl
}
int main()
{
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i ++) scanf("%d", &q[i]);
cout << quick_sort(q, 0, n-1 , k) << endl;
return 0;
}