Home > other >  stable partition in c - why is it O(n lg n)?
stable partition in c - why is it O(n lg n)?

Time:02-09

I was looking at the possible implementation of stable partition in c : https://en.cppreference.com/w/cpp/algorithm/ranges/stable_partition

it’s stated this is at worst O nlgn.

How is this possible? it seems like in the worst case a rotate is called at every index, resulting in an O n**2 algorithm.

CodePudding user response:

As ALX23z notes, the sample implementation is not conforming with respect to running time. Here is what an O(n log n) in-place stable_partition could look like (at least from an algorithms perspective; if you want a library-grade implementation go look at the actual libraries).

#include <algorithm>

template <typename Iterator, typename Predicate>
Iterator my_stable_partition(Iterator first, Iterator last,
                             Predicate predicate) {
  auto n = std::distance(first, last);
  if (n <= 1) {
    if (n == 1 && predicate(*first))
        first;
    return first;
  }
  auto middle = first;
  std::advance(middle, n / 2);
  auto a = my_stable_partition(first, middle, predicate);
  auto b = my_stable_partition(middle, last, predicate);
  return std::rotate(a, middle, b);
}

Here's a quick and dirty test.

#include "my_stable_partition.cc"
#include <assert.h>
#include <stdlib.h>
#include <vector>

bool odd(int n) { return n % 2 == 0; }

int main() {
  for (int i = 0; i < 1000; i  ) {
    std::vector<int> arr(i);
    long long checksum = 0;
    for (int &x : arr) {
      checksum  = x = random() / 31337;
    }
    auto mid = my_stable_partition(arr.begin(), arr.end(), odd);
    for (auto it = arr.begin(); it != mid;   it) {
      assert(odd(*it));
      checksum -= *it;
    }
    for (auto it = mid; it != arr.end();   it) {
      assert(!odd(*it));
      checksum -= *it;
    }
    assert(checksum == 0);
  }
}
  •  Tags:  
  • Related