Clasa a X-a · Divide et imperaRead in English

Sortarea rapidă (Quick Sort) în C++

În engleză: Quick sort

O(n log n)C++1768 de linii2 exemple

Ideea

Alegem un pivot (aici elementul din mijloc) și rearanjăm porțiunea astfel încât în stânga să ajungă valori <= pivot, iar în dreapta valori >= pivot: indicele i înaintează cât timp v[i] < pivot, j coboară cât timp v[j] > pivot, apoi v[i] și v[j] se interschimbă. Când i și j se încrucișează, sortăm recursiv cele două bucăți. Spre deosebire de interclasare, munca se face ÎNAINTE de autoapeluri și nu e nevoie de vector auxiliar.

Descrierea în engleză

We pick a pivot (here the middle element) and rearrange the portion so that values <= pivot end up on the left and values >= pivot on the right: index i advances while v[i] < pivot, j goes down while v[j] > pivot, then v[i] and v[j] are swapped. When i and j cross, we sort the two pieces recursively. Unlike merge sort, the work is done BEFORE the recursive calls and no helper array is needed.

Complexitate
O(n log n) în medie, O(n * n) în cazul cel mai nefavorabil
Clasa
Clasa a X-a (Grade 10)

Exemple

Exemplul 1

Intrare

8
5 2 9 1 5 6 3 8

Ieșire așteptată

1 2 3 5 5 6 8 9
Exemplul 2

Intrare

5
7 7 7 1 7

Ieșire așteptată

1 7 7 7 7

Codul C++

Codul complet, cu comentarii în română. Îl poți modifica liber și îl poți reseta oricând.

sortare-rapida.cpp
/*
 * Titlu: Sortarea rapidă (Quick Sort)
 * Clasa: 10
 * Capitol: Divide et impera
 * Descriere: Alegem un pivot (aici elementul din mijloc) și rearanjăm porțiunea
 *            astfel încât în stânga să ajungă valori <= pivot, iar în dreapta valori
 *            >= pivot: indicele i înaintează cât timp v[i] < pivot, j coboară cât
 *            timp v[j] > pivot, apoi v[i] și v[j] se interschimbă. Când i și j se
 *            încrucișează, sortăm recursiv cele două bucăți. Spre deosebire de
 *            interclasare, munca se face ÎNAINTE de autoapeluri și nu e nevoie de
 *            vector auxiliar.
 * Complexitate: O(n log n) în medie, O(n * n) în cazul cel mai nefavorabil
 *
 * Exemplu
 * Intrare:
 * 8
 * 5 2 9 1 5 6 3 8
 * Ieșire: 1 2 3 5 5 6 8 9
 *
 * Exemplu
 * Intrare:
 * 5
 * 7 7 7 1 7
 * Ieșire: 1 7 7 7 7
 */
#include <iostream>
using namespace std;

int v[100000];

void sortareRapida(int st, int dr)
{
    if (st >= dr)
        return;
    int pivot = v[(st + dr) / 2];
    int i = st, j = dr;
    while (i <= j)
    {
        while (v[i] < pivot)
            i++;
        while (v[j] > pivot)
            j--;
        if (i <= j)
        {
            int t = v[i];
            v[i] = v[j];
            v[j] = t;
            i++;
            j--;
        }
    }
    sortareRapida(st, j);
    sortareRapida(i, dr);
}

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> v[i];
    sortareRapida(0, n - 1);
    for (int i = 0; i < n; i++)
        cout << v[i] << ' ';
    cout << '\n';
    return 0;
}

Rulează pe un g++ adevărat (C++17, -O2) prin Compiler Explorer. Programele trebuie să se termine repede: există o limită de timp.