In this chapter, you implemented quicksort recursively. Here’s how you might do it iteratively.
This solution uses Lomuto’s partitioning strategy. You’ll leverage a stack to store pairs of high and low indices for sublist partitions.
void quicksortIterativeLomuto<E extends Comparable<E>>(
List<E> list,
) {
// 1
var stack = Stack<int>();
// 2
stack.push(0);
stack.push(list.length - 1);
// 3
while (stack.isNotEmpty) {
// 4
final high = stack.pop();
final low = stack.pop();
// 5
final pivot = _partitionLomuto(list, low, high);
// 6
if (pivot - 1 > low) {
stack.push(low);
stack.push(pivot - 1);
}
// 7
if (pivot + 1 < high) {
stack.push(pivot + 1);
stack.push(high);
}
}
}
Here’s how the solution works:
Create a stack that stores indices.
Push the starting low and high boundaries on the stack as initial values.
When the stack is empty, quicksort is complete.
Get the pair of high and low indices from the stack.
Perform Lomuto’s partitioning with the current indices. Recall that Lomuto picks the last element as the pivot and splits the partitions into three parts: elements that are less than the pivot, the pivot, and finally, elements that are greater than the pivot.
Once the partitioning is complete, add the lower bound’s low and high indices to partition the lower half later.
Similarly, add the upper bound’s low and high indices to partition the upper half later.
The results are the same as with the recursive version:
Merge sort is preferable over quicksort when you need stability. Merge sort is stable and guarantees O(n log n). These characteristics are not the case with quicksort, which isn’t stable and can perform as badly as O(n²).
Fojqe rect kahrs fejban hah livtow wina mvdaxragar ig fogu fdtowvanel lcoye obipelzr uqi trelluceg wrduitnuok qufohn. Diezkvugq xebmw rewg jdib igotachr uqo fkiboc ez o borqoqueon jxivb.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.