线性时间选择(Top K)

直接上代码:

#include
using namespace std;
const int maxn = 10000;
int kp[maxn], mid[maxn];
void InsertionSort(int kp[], int n) {
	for (int j, i = 1; i < n; i++) {
		int tmp = kp[i];
		for (j = i; j > 0 && kp[j - 1] > tmp; j--) {
			kp[j] = kp[j - 1];
		}
		kp[j] = tmp;
	}
}
int FindMidian(int kp[], int low, int high) {
	if (low == high) {
		return kp[0];
	}
	int length = high - low;
	int a = length % 5;
	int b = length-a;
	int flag;
	int index = low;
	if (length >= 5) {
		for (index = low; index < b; index += 5) {
			InsertionSort(kp+index, 5);
			int num = (index - low) / 5;
			mid[num] = kp[index + 2];
		}
	}
	if (a > 0) {
		InsertionSort(kp + index, a);
		int num = (index - low) / 5;
		if (a == 3) {
			mid[num] = kp[index + 1];
		}
		else if (a == 1) {
			mid[num] = kp[index];
		}
		else{
			mid[num] = kp[index + a / 2 - 1];
		}
		flag = b / 5 + 1;
	}
	else {
		flag = b / 5;
	}
	if (flag== 1)return mid[0];
	else {
		return FindMidian(mid, 0, flag);
	}
}
void swap(int arr[], int i, int j) {
	int tem;
	tem = arr[i];
	arr[i] = arr[j];
	arr[j] = tem;
}
int partition(int kp[], int L, int R) {
	int less = L - 1;
	int more = R;
	while (L < more) {
		if (kp[L] < kp[R]) {
			swap(kp, ++less, L++);
		}
		else if(kp[L]>kp[R]) {
			swap(kp, --more, L);
		}
		else {
			L++;
		}
	}
	swap(kp, R, more);
	int p = more;
	return p;
}
int KpSelsect(int kp[], int low, int high, int k) {
	int i;
	int midian = FindMidian(kp, low, high);
	for (i = low; i < high;i++) {
	if (kp[i] == midian) {
	break;
	}
	}
	swap(kp, i, high - 1);
	int index = partition(kp, low, high - 1);
	int len = index - low + 1;
	if (len == k) {
		return kp[index];
	}
	else if (k < len) {
		return KpSelsect(kp, low, len, k);
	}
	else {
		return KpSelsect(kp, index + 1, high, k - len);
	}
}
int main() {
	//text
	int kp[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13 };
	cout << FindMidian(kp, 0, 13) << endl;
	cout << KpSelsect(kp, 0, 13, 3);
}

你可能感兴趣的:(分治法)