Быстрая сортировка
Алгоритм
Выбираем в массиве опорный элемент. За Θ(N) делим массив на части: (<= опорного), (опорный), (>= опорного). Левую и правую части сортируем рекурсивно.
В лучшем случае, если опорный элемент будет делить массив примерно пополам, получим сложность O(NlogN), как у сортировки слиянием.
С другой стороны, если опорный элемент каждый раз выбирать неудачно (близко к минимуму или максимуму), то одна из половин будет почти пустой, а сложность деградирует до O(N2).
Если в качестве опорного выбирать любой фиксированный элемент, всегда можно составить контртест, на котором время работы будет квадратичным. Чтобы избежать худшего случая, требуется в качестве опорного выбирать случайный элемент в рассматриваемом диапазоне. Можно показать, что ожидаемая сложность при этом составит O(NlogN); константа у быстрой сортировки, как правило, меньше, чем у других сортировок с подобной асимптотической сложностью.
minstd_rand generator; void quickSort(vector<int> &a, int l, int r) { if (l >= r) return; uniform_int_distribution<int> distribution(l, r); swap(a[l], a[distribution(generator)]); int i = l + 1, j = r; while (1) { while (i <= j && a[i] < a[l]) i++; while (i <= j && a[j] > a[l]) j--; if (i > j) break; swap(a[i++], a[j--]); } swap(a[l], a[j]); quickSort(a, l, j - 1); quickSort(a, j + 1, r); }
K-я порядковая статистика за O(N)
minstd_rand generator; int quickSort(vector<int> &a, int l, int r, int k) { uniform_int_distribution<int> distribution(l, r); swap(a[l], a[distribution(generator)]); int i = l + 1, j = r; while (1) { while (i <= r && a[i] < a[l]) i++; while (j > l && a[j] > a[l]) j--; if (i >= j) break; swap(a[i++], a[j--]); } swap(a[l], a[j]); if (k < j) return quickSort(a, l, j - 1, k); if (k == j) return a[j]; else return quickSort(a, j + 1, r, k); }
Ссылки
Теория:
- neerc.ifmo.ru/wiki — Быстрая сортировка
- neerc.ifmo.ru/wiki — Поиск k-ой порядковой статистики
- algorithmica.org — Сортировки
- algs4.cs.princeton.edu/lectures — 2.3 Quicksort
- Brilliant.org — Quicksort
Демонстрация:
Код:
- indy256/codelibrary/java/sort/Quicksort.java
- indy256/codelibraryjava/sort/NthElement.java
- ADJA/algos/Other/QuickSort.cpp
- algs4.cs.princeton.edu/code — quicksort, quicksort with 3-way partitioning, optimized quicksort
Задачи: