Sortarea prin numărare (Counting Sort) în C++
Sortarea prin numărare (Counting Sort) este o metodă de sortare a vectorilor ce se bazează pe utilizarea unui vector de frecvență. Acest algoritm de sortare poate fi extrem de eficient în anumite situații, în funcție de intervalul de valori al elementelor vectorului. Vom considera că vrem să sortăm un vector de lungime indexat de la și cu elementele cuprinse între și
Algoritm
Se parcurge vectorul și se rețin frecvențele elementelor sale în vectorul de frecvență Apoi, se parcurge vectorul de la la dacă vrem să realizăm o sortare crescătoare, sau de la la în caz contrar. Considerăm noua lungime a vectorului, și o inițializăm cu Pentru fiecare element adăugăm valoarea la finalul vectorului (pe poziția ce mai întâi este incrementată) de ori, pentru că de atâtea ori apare aceasta în Ordinea în care este parcurs vectorul de frecvență ne garantează că elementele vor fi reintroduse în vector gata sortate.
Exemplu
Am notat vectorul inițial cu vectorul sortat cu iar vectorul de frecvență cu
Implementare în C++
Mai jos este implementarea algoritmului în C++. Nimic special… L-am parcurs pe de la la și am actualizat frecvența (numărul de apariții) ale elementului curent prin frq[v[i]]++
. Apoi, l-am parcurs pe de la la (pentru că ăsta e intervalul de valori al elementelor lui Pentru fiecare element cât timp e nenul, îl decrementez, incrementez noul capăt al lui și îl copiez acolo pe
for (int i = 1; i <= n; i++) frq[v[i]]++;int k = 0;for (int i = 0; i < MAX; i++) while (frq[i]--) v[++k] = i;
Se observă că sortarea prin numărare nu este un algoritm de sortare prin comparare, deoarece nu se efectuează nicio comparație între elementele vectorului. Soluția poate fi adaptată și pentru cazul în care intervalul de valori al lui conține și numere negative, așa cum am descris în articolul Vectori caracteristici. Vectori de frecvență.
În plus, dacă nu avem nevoie de forma inițială a vectorului (cea nesortată), putem calcula frecvențele încă din timpul citirii vectorului. De asemenea, dacă nu trebuie decât să afișăm vectorul sortat, putem afișa elementele direct în while
, fără să mai reconstruim vectorul. Iată mai jos o sursă completă care citește un șir de numere, și le afișează în ordine crescătoare, folosind sortarea prin numărare.
#include <bits/stdc++.h>using namespace std;const int MAX = 618;
int n;int frq[MAX];
int main() { cin >> n; for (int i = 0; i < n; i++) { int x; cin >> x; frq[x]++; } for (int i = 0; i < MAX; i++) while (frq[i]--) cout << i << ' '; cout << '\n'; return 0;}
Complexitate
Sortarea prin numărare face pași. Un de la parcurgerea lui un de la parcurgerea lui și încă un de la reintroducerea elementelor în Asta înseamnă o complexitate liniară, de ordinul Complexitatea spațiului auxiliar este pentru că este necesar un vector de frecvență de lungime
Totuși, deși complexitatea algoritmului este liniară, acesta nu este fezabil în orice condiții. El este eficient doar când lungimea intervalului de valori ale elementelor din vector este suficient de mică în raport cu lungimea vectorului. Mai exact, sortarea prin numărare bate un algoritm de complexitate cum ar fi QuickSort, atunci când Similar, sortarea prin numărare e mai bună decât un algoritm în ca sortarea prin selecție, când
Dacă aveți vreo întrebare despre metoda sortării prin numărare, nu ezitați să o adresați mai jos într-un comentariu