Skip to content

Instantly share code, notes, and snippets.

@goldsborough
Created October 24, 2015 22:28
Show Gist options
  • Save goldsborough/6abb54fb8a1e38fcd8fc to your computer and use it in GitHub Desktop.
Save goldsborough/6abb54fb8a1e38fcd8fc to your computer and use it in GitHub Desktop.
Quick-select algorithm to find the n-smallest elements.
template<typename Iterator>
Iterator part(Iterator begin, Iterator end)
{
auto pivot = begin++;
if (pivot == begin || begin == end) return pivot;
for (--end; begin != end; ++begin)
{
while (begin != end && *begin < *pivot) ++begin;
while (begin != end && *end > *pivot) --end;
if (begin == end) break;
std::swap(*begin, *end);
}
if (*begin > *pivot) --begin;
std::swap(*begin, *pivot);
return begin;
}
template<typename Iterator>
Iterator smallest_n(Iterator begin, Iterator end, std::size_t position)
{
if (begin == end || position == 0) return begin;
else if (std::distance(begin, end) <= position) return end;
while (true)
{
auto i = part(begin, end);
auto distance = std::distance(begin, i);
if (distance < position)
{
position -= (distance + 1);
begin = ++i;
}
else if (distance > position) end = i;
else return i;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment