快速排序|2018年藍橋杯B組題解析第五題-fishers


標題:快速排序

以下代碼可以從數組a[]中找出第k小的元素。

它使用了類似快速排序中的分治算法,期望時間復雜度是O(N)的。

請仔細閱讀分析源碼,填寫划線部分缺失的內容。

#include <stdio.h>
#include<cstdlib>

int quick_select(int a[], int l, int r, int k) {
	int p = rand() % (r - l + 1) + l; //l~r之間的一個隨機數 
	int x = a[p];//x的值隨機數a[p]的值 
	{int t = a[p]; a[p] = a[r]; a[r] = t;} //交換隨機數a[p]和高位右邊第一個數 
	int i = l, j = r; //i左指針 j右指針
	while(i < j) {
		while(i < j && a[i] < x) i++;// 最后i==j 或者 a[i]>=x
		if(i < j) {//如果a[i]>=隨機數x 
			a[j] = a[i]; //選一個比x大的數 放到高位 
			j--;
		}
		while(i < j && a[j] > x) j--;// 最后j==i 或者 a[i]<=x
		if(i < j) {//如果a[i]<=隨機數x
			a[i] = a[j]; //選一個比x小的數 放到低位
			i++;
		}
	}
	a[i] = x;
	p = i;//這里改了p的值 說明會用到p 
	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);//a數組不變 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, p+1, r, k-(i-l+1) 或者 a, p, r, k-i+l

思路:首先學會快速排序的划分思想(看下張圖理解快排的雙指針)

左指針l:確認i左邊都小於當前選定的樞紐
右指針r:確定j右邊都大於當前選定的樞紐
樞紐:快速排序單遍掃描,可以選第一個元素為樞紐,也可以隨機選元素作為樞紐。

這道題要我們找到數組中第k小的元素,
思路和快速排序一樣:划分,分解,合並

關鍵在於划分:

先看參數的作用:
這里的參數l表示左指針,r表示右指針(功能同快速排序一致)
參數1:a表示數組不變
參數2:l表示左指針下標邊界
參數2:r表示右指針下標邊界
參數4:k表示選擇第k小的元素

回到快速排序的各個指針的變化:
l~i區間內都是比樞紐小的,一共i-l+1個元素;
i+1~r都是比樞紐大的
如果i-l+1比k大,說明要在l~i-1中找;還是找第k個元素
如果i-l+1比k小,說明要在i+1~r某個值中找,這個值是多少呢?要看還需要找到新一輪遞歸中找第多少小的元素,這里新參數k就等於 原k減去當前一輪的l~i的個數 即k-(i-l+1)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM