В ru.cppreference.com мы видим, что std::stable_partition
выполняет O (n) перестановки, если нам разрешено использовать дополнительную память.Это я вижу.Каждый раз, когда мы находим элемент в диапазоне, где наш предикат равен false, мы обмениваем его в другой буфер.В конце мы можем просто скопировать этот дополнительный буфер в конец нашей успешной части.[Я также предполагаю, что в этом случае stable_partition
может быть реализовано только с помощью итераторов Forward]
Чего я не получаю, так это по ссылке: stable_partition
выполняет O (nlogn) перестановок, самое большее, еслинам не разрешено использовать дополнительную память.Вот моя попытка.
#include <utility>
namespace cho {
template <typename BidirIt, typename Pred>
BidirIt stable_partition(BidirIt begin, BidirIt end, Pred p) {
BidirIt next_p = begin;
for(BidirIt it = begin; it != end; ++it) {
if(it == begin && p(*it)) {
next_p++;
continue;
}
if(p(*it)) {
std::swap(*next_p++, *it);
// riplle back swapped element to keep stability
BidirIt cur = it;
do {
BidirIt prev = --cur; cur++;
std::swap(*cur--, *prev--);
} while(cur != next_p);
}
}
return next_p;
}
template <typename ForwardIt, typename Pred>
ForwardIt partition(ForwardIt begin, ForwardIt end, Pred p) {
ForwardIt next_p = begin;
for(ForwardIt it = begin; it != end; ++it) {
if(p(*it)) {
std::swap(*next_p++, *it);
}
}
return next_p;
}
}
В этом случае, я колеблюсь после обмена.Итак, если расстояние между двумя последовательными истинными случаями составляет k
, я выполню k
перестановки.Я думаю, что для моего алгоритма наихудший случай возникает, когда диапазон обратно разделен.Если есть p
элементов, в которых предикат равен false, и n-p
элементов, в которых предикат равен true, я получу O ((n - p) * p) перестановки.Я думал об этом, и я не мог видеть, как я могу получить худший случай O (nlogn).
Реализации в LLVM, я проверил, но не смог понять, как достигается O (nlogn) перестановка.
PS: Моя реализация может быть неправильной.Я проверил это с парой входов, но это все.