选择问题 -线性时间选择
问题描述:
元素选择问题:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素。
线性时间选择算法:
模仿快速排序算法,
首先对输入数组进行划分,
然后对划分出的子数组之一进行递归处理。
对于给定的n个元素的数组a[0:n—1],要求从中找出第k小的元素。
输入;输入有多组测试例。
对每一个测试例有2行,第一行是整数n和k(1≤k<n≤1000),第二行是n个整数。
快速排序的基本思想:
首先选第一个数作为分界数据,
将比它小的数据存储在它的左边,比它大的数据存储在它的右边,它存储在左、右两个子集之间。
这样左、右子集就是原问题分解后的独立子问题。
再用同样的方法,继续解决这些子问题,直到每个子集只有一个数据,就完成了全部数据的排序工作。`在这里
//选择问题
//采用分治策略找出第k小元素的算法
#include<iostream>
#define NUM 1001
using namespace std;
int a[NUM];
int select(int left, int right, int k)
{
//找到了第k小的元素
if (left >= right)
return a[left];
int i = left; //从左向右的指针
int j = right + 1; //从右向左的指针
//把最左边的数据作为分解数据
int pivot = a[left];
//把左边大于pivot的元素与右侧小于pivot的元素交换
while (true)
{
//在左侧寻找>=pivot的元素
do {
i = i + 1; //先将指针指向要进行判断的元素,然后再进行判断,如果不满足判断条件,指针将继续指向该元素
} while (a[i] < pivot);
//在右侧寻找《=pivot的元素
do {
j = j + 1;
} while (a[j] > pivot);
if (i >= j)
break;//没有发现交换对象
swap(a[i], a[j]); //如果发现左边的有大于pivot,右边有小于pivot的则将两者进行交换
}
if (j - left + 1 == k)
return pivot;
a[left] = a[j];
a[j] = pivot;
if (j - left + 1 < k)
return select(j + 1, right, k - j + left - 1);
else
return select(left, j - 1, k);
}
int main()
{
int n,m;
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
int j = select(0, n - 1, m);
cout << a[j];
}