例子:6,1,8,2,9,5,7,找出第 2 到 5 小的子数组。
对上面数组排序后得到 1,2,5,6,7,8,9,很容易看出其中 第 2 ~ 5 小的区间中的所有数为 2,5,6,7。
代码:
#include <iostream> #include <fstream> int flag = 0; void Qselect(int arr[], int low, int high, int k1, int k2) { if (high <= low) return; // 当左边大于等于右边 则退出 int i = low; int j = high + 1; int key = arr[low]; // 可随意选择一个位置 while (true) { while (arr[++i] < key) if (i == high) break; while (arr[--j] > key) if (j == low) break; if (i >= j) break; // 当左边大于等于右边 则退出循环 int temp = arr[i]; // 交换 i 和 j 位置上的数据 arr[i] = arr[j]; arr[j] = temp; } int temp = arr[low]; // 交换 low 和 j 位置上的数据 arr[low] = arr[j]; arr[j] = temp; if (j > k1) // 如果划分点大于 k1 { if (j == k2) // 如果分割点为第 k2 小的位置 记录状态 flag = 1; Qselect(arr, low, j - 1, k1, k2); // 对 low ~ j - 1 部分进行一次一定程度上的排序(位置交换) } else if (j < k1) Qselect(arr, j + 1, high, k1, k2); // 对 low ~ j - 1 部分进行一次一定程度上的位置交换 else return; // 如果分割点正好为第 k1 小的位置 跳出递归 } int main() { int arr[1001], n, k1, k2; std::cout << "请输入无序数列大小:"; std::cin >> n; std::cout << "请输入无序数列元素:"; for (int i = 0; i < n; i++) std::cin >> arr[i]; std::cout << "请指定区间范围:"; std::cin >> k1 >> k2; Qselect(arr, 0, n, k1, k2); if (flag) { // 如果提前得到 k2 分割点 则可以直接输出 for (int i = k1; i <= k2; i++) std::cout << arr[i] << " "; } else { // 否则将分割点 k1 到 n 部分再次执行快速选择算法 Qselect(arr, k1, n, k2, k1); for (int i = k1; i <= k2; i++) std::cout << arr[i] << " "; } return 0; }
原文:https://www.cnblogs.com/darkchii/p/13209069.html