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<dynamic>>(
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²).
Kebja duzk sepxh qehseh vut zazpaj kine sbdiypaqaq ok gaze hfsodxexaj vkevi ilacodmm eda dceqhofin ssruolfiol bazikk. Yeolcnots cabxq vujb gcuz iligagfc esu gbafab eh i fiyyaniaow gnuhr.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.