题目描述
快速排序 - 蓝桥云课 (lanqiao.cn)
#include <stdio.h>
int quick_select(int a[], int l, int r, int k) {
int p = rand() % (r - l + 1) + l;
int x = a[p];
{int t = a[p]; a[p] = a[r]; a[r] = t;}
int i = l, j = r;
while(i < j) {
while(i < j && a[i] < x) i++;
if(i < j) {
a[j] = a[i];
j--;
}
while(i < j && a[j] > x) j--;
if(i < j) {
a[i] = a[j];
i++;
}
}
a[i] = x;
p = i;
if(i - l + 1 == k) return a[i];
if(i - l + 1 < k) return quick_select( _____________________________ ); //填空
else return quick_select(a, l, i - 1, k);
}
int main()
{
int a[100];
int n;
scanf("%d %d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
printf("%d\n", quick_select(a, 0, n-1, 5));
return 0;
}
题目分析
对于此题首先需要了解快速排序,简单概述如下:
给出两个指针,分别在数组的左端点与右端点,两个指针分别向中间移动,如果大小的相对位置相反了就交换这两个数,如果两指针相遇就分别左右再次递归来交换数。
在本题中,需要进行的填空为对于右边递归的判断,此时前i - l + 1个数已经过去,所以在后半部分求整体第k小的数的时候需要减去前i - l + 1个数,也就是此时求此段的第k - (i - l + 1)个数
#include <stdio.h>
int quick_select(int a[], int l, int r, int k) {
int p = rand() % (r - l + 1) + l;
int x = a[p];
{int t = a[p]; a[p] = a[r]; a[r] = t;}
int i = l, j = r;
while(i < j) {
while(i < j && a[i] < x) i++;
if(i < j) {
a[j] = a[i];
j--;
}
while(i < j && a[j] > x) j--;
if(i < j) {
a[i] = a[j];
i++;
}
}
a[i] = x;
p = i;
if(i - l + 1 == k) return a[i];
if(i - l + 1 < k) return quick_select( a, i + 1, r, k - (i - l + 1)); //填空
else return quick_select(a, l, i - 1, k);
}
int main()
{
int a[100];
int n;
scanf("%d %d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
printf("%d\n", quick_select(a, 0, n-1, 5));
return 0;
}