Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lomuto's Partition, stable or not?

I tried to search on Web and in my algorithms book if the Lomuto's specific solution of QSort Partition is stable or not (I know that the Hoare's version is unstable) but i didn't find a precise answer.
So I've tried to make same examples and it seems stable. But I didn't demonstrate it. Could you help me? If it is not stable, could you find me an example of input?

like image 882
Gengiolo Avatar asked Jul 10 '11 12:07

Gengiolo


People also ask

How does Lomuto partition work?

Lomuto's Partition Scheme: This algorithm works by assuming the pivot element as the last element. If any other element is given as a pivot element then swap it first with the last element.

What does Hoare partition do?

Hoare partition is an algorithm that is used to partition an array about a pivot. All elements smaller than the pivot are on it's left (in any order) and all elements greater than the pivot are on it's right (in any order). Quicksort algorithm uses hoare paritition to partition the array.

Which type of partitioning is used in Quicksort?

Quicksort is a Divide and Conquer Algorithm that is used for sorting the elements. In this algorithm, we choose a pivot and partitions the given array according to the pivot.


1 Answers

I'm going to interpret "Quicksort with Lomuto's partition" as referring to the algorithm from here (slides 21–22).

This algorithm is unstable on the array [a, b, c] where c < a = b.


I found this counterexample by implementing the Quicksort algorithm in Python so that (like Python's built-in sort) it takes a key function. By supplying an appropriate key function, I can make the sort think that certain elements are identical, but I can still distinguish them. Then it's just a matter of trying lots of permutations and spotting instability. The code below certainly doesn't exhaust the possible tests (one might want to try more than two identical elements, or multiple sets of identical elements), but it was good enough in this case.

def lomuto(A, key=lambda x:x):
    def partition(A, p, r):
        i = p - 1
        pivot = A[r]
        for j in range(p, r):
            if key(A[j]) <= key(pivot):
                i += 1
                A[i], A[j] = A[j], A[i]
        A[i+1], A[r] = A[r], A[i+1]
        return i + 1

    def quicksort(A, p, r):
        if p < r:
            q = partition(A, p, r)
            quicksort(A, p, q-1)
            quicksort(A, q+1, r)

    quicksort(A, 0, len(A) - 1)

def test_stability(f, n):
    """Try to discover if the sorting function f is stable on n inputs;
printing the first counterexample found, if any."""
    import itertools
    for i in range(n - 1):
        def order(P): return P.index((i, 0)) < P.index((i, 1))
        array = [(j, 0) for j in range(n - 1)] + [(i, 1)]
        for P in map(list, itertools.permutations(array)):
            Q = P[:] # take a copy
            f(Q, key=lambda x: x[0])
            if order(P) != order(Q):
                print(P, '->', Q)
                return

>>> test_stability(lomuto, 3)
[(1, 0), (1, 1), (0, 0)] -> [(0, 0), (1, 1), (1, 0)]
like image 181
Gareth Rees Avatar answered Oct 03 '22 19:10

Gareth Rees