-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Open
Labels
confirmedVerified by a second partyVerified by a second partylibc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Description
The reproduction program is almost the same as my 7 year old one for std::sort that got fixed only recently:
#include <algorithm>
#include <iostream>
#include <vector>
void make_killer(int size, std::vector<int>& v) {
int candidate = 0;
int num_solid = 0;
int gas = size - 1;
std::vector<int> tmp(size);
v.resize(size);
for (int i = 0; i < size; ++i) {
tmp[i] = i;
v[i] = gas;
}
std::nth_element(tmp.begin(), tmp.end() - 2, tmp.end(), [&](int x, int y) {
if (v[x] == gas && v[y] == gas) {
if (x == candidate) v[x] = num_solid++;
else v[y] = num_solid++;
}
if (v[x] == gas) candidate = x;
else if (v[y] == gas) candidate = y;
return v[x] < v[y];
});
}
int main(int argc, char** argv) {
std::vector<int> v;
int comparison_count;
auto counter = [&](int x, int y) { ++comparison_count; return x < y; };
std::cout << "N: comparisons\n";
for (int i = 100; i <= 6400; i *= 2) {
// to nullify small constants we multiply by 100
make_killer(i, v);
comparison_count = 0;
std::nth_element(v.begin(), v.end() - 2, v.end(), counter);
std::cout << i << ": " << comparison_count << "\n";
}
return 0;
}The output:
N: comparisons
100: 2741
200: 10491
400: 40991
800: 161991
1600: 643991
3200: 2567991
6400: 10255991Evidently quadratic, but the standard requires:
Complexity: For the overloads with no ExecutionPolicy, linear on average. For the overloads
with an ExecutionPolicy,O(N)applications of the predicate, andO(N log N)swaps, whereN = last - first.
The problem is that pure quickselect is implemented without a fallback for worst cases, like median of medians.
Morwenn
Metadata
Metadata
Assignees
Labels
confirmedVerified by a second partyVerified by a second partylibc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.