Вкратце: Можно ли эффективно реализовать быструю сортировку двусвязного списка? До того, как я подумал об этом, я понял, что нет.
На днях у меня была возможность рассмотреть требования к итератору для базовых алгоритмов сортировки. Основные O(N²) довольно просты.
- Пузырьковая сортировка — 2 прямых итератора прекрасно подойдут, один перетаскивая за другим.
- Сортировка вставками — подойдут 2 двунаправленных итератора. Один для неупорядоченного элемента, один для точки вставки.
- Сортировка выбором. Немного сложнее, но прямые итераторы могут помочь.
Быстрая сортировка
Introsort_loop в std::sort (как в стандартной библиотеке gnu/hp(1994)/silicon Graphics(1996)) требует, чтобы он был random_access.
__introsort_loop(_RandomAccessIterator __first,
_RandomAccessIterator __last,
_Size __depth_limit, _Compare __comp)
Как я и ожидал.
Теперь, при ближайшем рассмотрении, я не могу найти настоящую причину, по которой это требуется для быстрой сортировки. Единственное, что явно требует random_access_iterators, — это вызов std::__median
, требующий вычисления среднего элемента. Обычная обычная быстрая сортировка не вычисляет медиану.
Разделение состоит из чека
if (!(__first < __last))
return __first;
Не очень полезная проверка для двунаправленности. Однако это можно заменить проверкой предыдущего прохода разбиения (слева направо/справа налево) с простым условием
if ( __first == __last ) this_partitioning_is_done = true;
Можно ли реализовать быструю сортировку достаточно эффективно, используя только двунаправленные итераторы? Рекурсивная глубина все еще может быть защищена.
NB. Я еще не пробовал фактическую реализацию.
std::rotate
иstd::upper_bound
для реализации вставок, и оба ингредиента требуют только прямых итераторов. Конечно, это все еще O (N ^ 2). - person TemplateRex   schedule 13.07.2012