蓝桥杯第九届省赛 快速排序(分治)

                                             标题:快速排序

以下代码可以从数组a[]中找出第k小的元素。


它使用了类似快速排序中的分治算法,期望时间复杂度是O(N)的。


请仔细阅读分析源码,填写划线部分缺失的内容。

#include

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[] = {1, 4, 2, 8, 5, 7, 23, 58, 16, 27, 55, 13, 26, 24, 12};
    printf("%d\n", quick_select(a, 0, 14, 5));
    return 0;
}
注意:只填写划线部分缺少的代码,不要抄写已经存在的代码或符号。

答案:a, i + 1, r, k - (i - l + 1)

代码分析: 

#include 
#include 
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循环实现此功能:将数组中所有比x的值大放x左边,将所有比x值小的值放x右边
		while (i < j && a[i] < x) i++;//找到左边第一个比x值大的数
		if (i < j) {
			a[j] = a[i];	//放至x右边
			j--;
		}
		while (i < j && a[j] > x) j--;	//找到右边第一个比x值小的数
		if (i < j) {
			a[i] = a[j];	//放至x左边
			i++;
		}
	}
	a[i] = x;//比x小值放左边,比x大值放右边后,i即为x值
	p = i;//这行没太大作用,加不加都一样
	if (i - l + 1 == k) return a[i];	//比x小的数 + 1 = k,即x为第k小的数
	/*
		比x小的数 + 1 < k,说明x太小了,应该去比x大的值(x的右边)里面再找数[x新]
		但不需要再找k - 1个比[x新]小的数,已经确定了(i - 1 + 1)个比[x新]小的值
		更新查询区间为(i + 1, r)
		找第k - (i - l + 1)小的数
	*/
	if (i - l + 1 < k) return quick_select(a, i + 1, r, k - (i - l + 1)); //填空
	/*
		比x大的数 + 1 > k,说明x太大了,应该去x左边找[x新]
		更新查询区间(l, i + 1)
		找第k小的数
	*/
	else return quick_select(a, l, i - 1, k);
}

int main(){
	int a[] = { 1, 4, 2, 8, 5, 7, 23, 58, 16, 27, 55, 13, 26, 24, 12 };
	printf("%d\n", quick_select(a, 0, 14, 5));
	/*for (int i = 0; i < 15; ++i) {
		printf("%d ", a[i]);
	}
	putchar('\n');*/
	return 0;
}

 

你可能感兴趣的:(蓝桥杯第九届省赛 快速排序(分治))