0% found this document useful (0 votes)
12 views3 pages

Hoare vs. Lomuto Partitioning Methods

Lomuto's partitioning method for Quicksort may be simpler to implement than Hoare's method, but it performs worse in several ways: 1) Lomuto's method requires on average 3 times as many swaps as Hoare's method to partition an array. 2) On an already sorted array, Hoare's method requires no swaps while Lomuto's still requires around n swaps. 3) For arrays with equal elements, Lomuto's method can degrade to O(n^2) time while Hoare's remains O(n log n) time. Due to its performance issues, Lomuto's method should not be used for implementing a production sorting
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views3 pages

Hoare vs. Lomuto Partitioning Methods

Lomuto's partitioning method for Quicksort may be simpler to implement than Hoare's method, but it performs worse in several ways: 1) Lomuto's method requires on average 3 times as many swaps as Hoare's method to partition an array. 2) On an already sorted array, Hoare's method requires no swaps while Lomuto's still requires around n swaps. 3) For arrays with equal elements, Lomuto's method can degrade to O(n^2) time while Hoare's remains O(n log n) time. Due to its performance issues, Lomuto's method should not be used for implementing a production sorting
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Pedagogical Dimension

Due to its simplicity Lomuto's partitioning method might be easier to implement. There is a nice
anecdote in Jon Bentley's Programming Pearl on Sorting:
Most discussions of Quicksort use a partitioning scheme based on two approaching indices [...]
[i.e. Hoare's]. Although the basic idea of that scheme is straightforward, I have always found the
details tricky - I once spent the better part of two days chasing down a bug hiding in a short
partitioning loop. A reader of a preliminary draft complained that the standard two-index method
is in fact simpler than Lomuto's and sketched some code to make his point; I stopped looking
after I found two bugs.

Performance Dimension
For practical use, ease of implementation might be sacrificed for the sake of efficiency. On a
theoretical basis, we can determine the number of element comparisons and swaps to compare
performance. Additionally, actual running time will be influenced by other factors, such as
caching performance and branch mispredictions.
As shown below, the algorithms behave very similar on random permutations except for the
number of swaps. There Lomuto needs thrice as many as Hoare!

Number of Comparisons
Both methods can be implemented using
comparisons to partition an array of length .
This is essentially optimal, since we need to compare every element to the pivot for deciding
where to put it.

Number of Swaps
The number of swaps is random for both algorithms, depending on the elements in the array. If
we assume random permutations, i.e. all elements are distinct and every permutation of the
elements is equally likely, we can analyze the expected number of swaps.
As only relative order counts, we assume that the elements are the numbers
the discussion below easier since the rank of an element and its value coincide.

Lomuto's Method

. That makes

The index variable scans the whole array and whenever we find an element
smaller than
pivot , we do a swap. Among the elements
, exactly
ones are smaller than , so
we get
swaps if the pivot is .
The overall expectation then results by averaging over all pivots. Each value in
equally likely to become pivot (namely with prob.
), so we have

swaps on average to partition an array of length

is

with Lomuto's method.

Hoare's Method
Here, the analysis is slightly more tricky: Even fixing pivot
random.

, the number of swaps remains

More precisely: The indices and run towards each other until they cross, which always
happens at (by correctness of Hoare's partitioning algorithm!). This effectively divides the
array into two parts: A left part which is scanned by and a right part scanned by .
Now, a swap is done exactly for every pair of misplaced elements, i.e. a large element (larger
than , thus belonging in the right partition) which is currently located in the left part and a
small element located in the right part. Note that this pair forming always works out, i.e. there
the number of small elements initially in the right part equals the number of large elements in the
left part.
One can show that the number of these pairs is hypergeometrically
distributed: For the
large elements we randomly draw their positions in the array and have
positions in the left part. Accordingly, the expected number of pairs is
given that the pivot is .
Finally, we average again over all pivot values to obtain the overall expected number of swaps
for Hoare's partitioning:

(A more detailed description can be found in my master's thesis, page 29.)

Memory Access Pattern

Both algorithms use two pointers into the array that scan it sequentially. Therefore both behave
almost optimal w.r.t. caching.

Equal Elements and Already Sorted Lists


As already mentioned by Wandering Logic, the performance of the algorithms differs more
drastically for lists that are not random permutations.
On an array that is already sorted, Hoare's method never swaps, as there are no misplaced pairs
(see above), whereas Lomuto's method still does its roughly
swaps!
The presence of equal elements requires special care in Quicksort. (I stepped into this trap
myself; see my master's thesis, page 36, for a Tale on Premature Optimization) Consider as
extreme example an array which filled with s. On such an array, Hoare's method performs a
swap for every pair of elements - which is the worst case for Hoare's partitioning - but and
always meet in the middle of the array. Thus, we have optimal partitioning and the total running
time remains in
.
Lomuto's method behaves much more stupidly on the all array: The comparison A[j] <= x
will always be true, so we do a swap for every single element! But even worse: After the loop,
we always have
, so we observe the worst case partitioning, making the overall performance
degrade to
!

Conclusion
Lomuto's method is simple and easier to implement, but should not be used for implementing a
library sorting method.

Common questions

Powered by AI

The expected number of swaps in Lomuto's partitioning method is determined by averaging over all possible pivots, assuming each element has an equal chance of being the pivot. In contrast, Hoare's swaps depend on hypergeometrically distributed pairs of misplaced elements, which vary according to pivot selection, leading to random swap counts that are analyzed comprehensively in advanced methods .

While both methods can efficiently partition random permutations, Lomuto's approach results in approximately three times more swaps compared to Hoare's partitioning method. This is due to Lomuto's habit of swapping whenever a smaller element than the pivot is found, whereas Hoare only swaps misplaced elements between its two parts .

A developer might choose Lomuto's method for educational purposes due to its simplicity and ease of understanding. Its single-loop implementation reduces complexity, making it more approachable for learning and grasping the basic principles of partitioning without contending with the dual-index complications inherent in Hoare's method .

Both Lomuto's and Hoare's partitioning methods use pointers that sequentially scan the array, which ensures their memory access patterns are nearly optimal with respect to caching. This behavior helps reduce cache misses and improves execution efficiency .

Hoare's partitioning method is more suitable for a library sorting method due to its efficiency in reducing the number of swaps and better handling of edge cases such as already sorted or repeated elements. Despite its implementation complexity, its performance benefits outweigh these drawbacks, whereas Lomuto’s excessive swaps and degradation in specific cases make it less optimal for library-level applications .

The presence of repeated elements greatly impacts Lomuto's method, leading to excessive and inefficient swaps for each element as the comparison is always true, resulting in poor performance. In contrast, Hoare's method is less affected, as it still manages optimal partitioning due to its paired swapping strategy, although it also performs poorly in a worst-case scenario with repeated elements .

Lomuto's partitioning method is simpler and easier to implement due to its straightforward approach, where only one index scans the array. However, Hoare's method, despite being conceptually straightforward, can be detailed and tricky to implement correctly. Challenges with Hoare's method include dealing with two indices moving towards each other, which requires careful handling to avoid bugs .

When all elements are identical, Lomuto's method inefficiently swaps each element with itself, leading to maximum swaps and worst-case performance. Hoare's method, by altering its partitioning approach, still swaps every element pair but does it more systematically, allowing for at least an optimal partition location in the array, although the time complexity degrades .

Probability plays a crucial role in Hoare's analysis of swap counts as it relies on the distribution of misplaced elements, which follows a hypergeometric distribution. This statistical consideration helps determine the expected number of swaps by evaluating possible positions for each element within the array relative to selected pivots .

Hoare's partitioning method performs optimally on arrays that are already sorted, as it never performs swaps in such cases. This contrasts with Lomuto's method, which continues to perform unnecessary swaps even when no elements are misplaced .

You might also like