c++實現最壞時間爲線性時間的快速選擇算法

上圖是算法導論第三版第九章9.3所給出的步驟,根據這個步驟可以得到下面的代碼

/* 找中位數,只有五個數,直接排序取中間那個即可 */
int findMedian(vector<int> & nums, const int & left, const int & right) {
	sort(nums.begin() + left, nums.begin() + right);
	return nums[(left + right) >> 1];
}
/* 線性時間選擇第 k 小的數字 */
int linerTimeSelect(vector<int> & nums, const int & left, const int & right, const int & k) {
	if (right – left < 75) {
		sort(nums.begin() + left, nums.begin() + right);
		return nums[left + k];
	}
	/* 五個數字一組 */
	int nGroupCount = (right - left) / 5;
	/* 中位數集合 */
	vector<int> medians(nGroupCount);
	for (int i = 0; i < nGroupCount; ++i) {
		medians[i] = findMedian(nums, left + i * 5, left + (i + 1) * 5);
	}
	int nMedian = linerTimeSelect(medians, 0, nGroupCount, nGroupCount >> 1);
	vector<int> S1;
	vector<int> S2;
	int nSameCount = 0; 	// 用來記錄相等元素的個數
	for (int i = left; i < right; ++i) {
		if (nums[i] < nMedian) {
			S1.push_back(nums[i]);
		}
		else if (nums[i] > nMedian) {
			S2.push_back(nums[i]);
		}
		else {
			nSameCount++;
		}
	}
	/* 在低位找 */
	if (k < S1.size()) {
		return linerTimeSelect(S1, 0, S1.size(), k);
	}
	/* 在中間找 */
	else if (k < S1.size() + nSameCount) {
		return nMedian;
	}
	/* 在高位找 */
	else {
		return linerTimeSelect(S2, 0, S2.size(), k - S1.size() - nSameCount);
	}
	return -1;
}

k是數組下標,比如要求第5小的數組,k應該讓它等於4

S1是小於median的數構成的數組

S2是大於median的數構成的數組

這段代碼和原書所給出的步驟有一點差異,主要是對於partition函數,我採用了數組實現,即小於median的數放在S1,大於median的數放在S2,然後通過S1和S2來繼續劃分而不是通過原數組加上兩個指針進行劃分,這樣便於代碼的實現但是降低了一點效率,還有一個小差異就是分組的時候,有一組可能不滿5個,我們不用管這一組元素,最後劃分的時候自然會被劃分進去。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章