Grade 10 · Divide and conquerCitește în română
Merge sort
Original: Sortarea prin interclasare (Merge Sort)
The idea
We split the array into two halves, sort each half recursively, then merge them: we always compare the first remaining elements of the two halves and move the smaller one into a helper array. At the end we copy the result back. A portion with one element is already sorted. We use <= when comparing, so the sort is stable (equal elements keep their order).
Original description (Romanian)
Împărțim vectorul în două jumătăți, sortăm recursiv fiecare jumătate, apoi le interclasăm: comparăm mereu primele elemente rămase din cele două jumătăți și îl mutăm pe cel mai mic într-un vector auxiliar. La final copiem rezultatul înapoi. O porțiune cu un element este deja sortată. Folosim <= la comparare, deci sortarea este stabilă (elementele egale își păstrează ordinea).
- Complexity
- O(n log n) in every case, with O(n) extra memory
- Grade
- Grade 10 (Clasa a X-a)
- Chapter
- Divide and conquer
Examples
Input
8 5 2 9 1 5 6 3 8
Expected output
1 2 3 5 5 6 8 9
Input
3 3 2 1
Expected output
1 2 3
The code
Comments are in Romanian, as in the original collection. Edit freely: you can reset at any time.
/*
* Titlu: Sortarea prin interclasare (Merge Sort)
* Clasa: 10
* Capitol: Divide et impera
* Descriere: Împărțim vectorul în două jumătăți, sortăm recursiv fiecare jumătate,
* apoi le interclasăm: comparăm mereu primele elemente rămase din cele
* două jumătăți și îl mutăm pe cel mai mic într-un vector auxiliar.
* La final copiem rezultatul înapoi. O porțiune cu un element este deja
* sortată. Folosim <= la comparare, deci sortarea este stabilă
* (elementele egale își păstrează ordinea).
* Complexitate: O(n log n) în orice caz, cu memorie suplimentară O(n)
*
* Exemplu
* Intrare:
* 8
* 5 2 9 1 5 6 3 8
* Ieșire: 1 2 3 5 5 6 8 9
*
* Exemplu
* Intrare:
* 3
* 3 2 1
* Ieșire: 1 2 3
*/
#include <iostream>
using namespace std;
int v[100000], aux[100000];
void interclaseaza(int st, int m, int dr)
{
int i = st, j = m + 1, k = 0;
while (i <= m && j <= dr)
{
if (v[i] <= v[j])
aux[k++] = v[i++];
else
aux[k++] = v[j++];
}
while (i <= m)
aux[k++] = v[i++];
while (j <= dr)
aux[k++] = v[j++];
for (int t = 0; t < k; t++)
v[st + t] = aux[t];
}
void sorteaza(int st, int dr)
{
if (st >= dr)
return;
int m = (st + dr) / 2;
sorteaza(st, m);
sorteaza(m + 1, dr);
interclaseaza(st, m, dr);
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> v[i];
sorteaza(0, n - 1);
for (int i = 0; i < n; i++)
cout << v[i] << ' ';
cout << '\n';
return 0;
}
Runs on a real g++ (C++17, -O2) through Compiler Explorer. Keep runs short; there's a time limit.