Быстрая сортировка: различия между версиями

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску
Нет описания правки
 
(не показана 1 промежуточная версия этого же участника)
Строка 8: Строка 8:
Если в качестве опорного выбирать любой фиксированный элемент, всегда можно составить контртест, на котором время работы будет квадратичным. Чтобы избежать худшего случая, требуется в качестве опорного выбирать случайный элемент в рассматриваемом диапазоне. Можно показать, что ожидаемая сложность при этом составит O(NlogN); константа у быстрой сортировки, как правило, меньше, чем у других сортировок с подобной асимптотической сложностью.
Если в качестве опорного выбирать любой фиксированный элемент, всегда можно составить контртест, на котором время работы будет квадратичным. Чтобы избежать худшего случая, требуется в качестве опорного выбирать случайный элемент в рассматриваемом диапазоне. Можно показать, что ожидаемая сложность при этом составит O(NlogN); константа у быстрой сортировки, как правило, меньше, чем у других сортировок с подобной асимптотической сложностью.


minstd_rand generator;
  void quickSort(vector<int> &a, int l, int r) {
  void quickSort(vector<int> &a, int l, int r) {
     if (l >= r)
     if (l >= r)
Строка 17: Строка 19:
     int i = l + 1, j = r;
     int i = l + 1, j = r;
     while (1) {
     while (1) {
         while (i <= r && a[i] < a[l])
         while (i <= j && a[i] < a[l])
             i++;
             i++;
         while (j > l && a[j] > a[l])
         while (i <= j && a[j] > a[l])
             j--;
             j--;
         if (i >= j)
         if (i > j)
             break;
             break;
         swap(a[i++], a[j--]);
         swap(a[i++], a[j--]);
Строка 34: Строка 36:
   
   
  minstd_rand generator;
  minstd_rand generator;
 
  {{Changed|int}} quickSort(vector<int> &a, int l, int r, {{Changed|1=int k}}) {
  {{Changed|int}} quickSort(vector<int> &a, int l, int r, {{Changed|1=int k}}) {
     uniform_int_distribution<int> distribution(l, r);
     uniform_int_distribution<int> distribution(l, r);

Текущая версия от 02:35, 11 ноября 2022

Алгоритм

Выбираем в массиве опорный элемент. За Θ(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);
}

Ссылки

Теория:

Демонстрация:

Код:

Задачи: