Нерекурсивные варианты рекурсивных алгоритмов в реальности используются довольно редко, поскольку зачастую они сводятся просто к ручной реализации стека (то, что называется "закат солнца вручную"). Помимо увеличения сложности алгоритма на пустом месте, подобный подход требует выделить под этот ручной стек область памяти неизвестного заранее размера, а лишнее динамическое выделение памяти - это всегда плохо.
Чаще всего используют "полурекурсивные" варианты, в котором одна из веток сортируется рекурсивно, а вторая - в цикле. Условная схема:
fn sort(array, low, hi) {
while (low < hi) {
middle = partition(array, low, high);
sort(array, low, middle); // левая ветка сортируется рекурсивно
low = middle; // правая ветка сортируется без рекурсии
}
}
Также популярным "трюком" является переключение на другие алгоритмы при выполнении некоторых условий, а именно на сортировку вставками для малых массивов и на пирамидальную сортировку при превышении лимита рекурсии.
Алгоритм быстрой сортировки, использующий этот трюк, называется Introsort.
Вот результаты быстрого анализа стандартных библиотек:
- C# - используется полурекурсивный Introsort;
- Java - используется полурекурсивный Dual Pivot Quicksort (тоже с трюками);
- C++ - используется полурекурсивный Introsort;
- Python - используется вообще TimSort, относящийся к классу сортировок слиянием.
Как видно, нерекурсивная быстрая сортировка не используется. И чистая классическая тоже не используется.