#include <algorithm>
// 快速排序方式的选第K小的数
// (如果是选“大”的数, 可以把比较用greater, 或者选第n-k个)
template<typename T, class _Pr>
int get_pos(T* data, int n, int k, _Pr _Pred)
{
int h = 0;
int t = n - 1;
while (h < t)
{
// 从前向后找一个大的
for (; h < n; ++h)
{
if (_Pred(data[k], data[h]))
{
break;
}
}
// 从后向前找一个小的
for (; t > 0; --t)
{
if (_Pred(data[t], data[k]))
{
break;
}
}
if (h < t)
{
// 交换, 继续
std::swap(data[h], data[t]);
continue;
}
// 无需移动
if (h >= k && t <= k)
{
return k;
}
if (h > k)
{
// t更接近
std::swap(data[k], data[t]);
return t;
}
else
{
// h更接近
std::swap(data[h], data[k]);
return h;
}
}
return 0;
}
template<typename T, class _Pr>
int selectK(T* data, int n, int k, _Pr _Pred)
{
int head = 0;
int end = n;
int pos = get_pos(data, n, k, _Pred);
while (pos != k)
{
if (pos < k)
{
head = pos + 1;
}
else
{
end = pos;
}
int p = get_pos(data + head, end - head, k - head, _Pred);
pos = head + p;
}
return k;
}
template<typename T>
int selectK(T* data, int n, int k)
{
return selectK(data, n, k, std::less<>());
}