Sortarea unui vector
Una dintre cele mai frecvente operații cu vectori este sortarea - aranjarea elementelor într-o anumită ordine (crescătoare sau descrescătoare).
Exemple:
3 7 2 9 4sortat crescător:2 3 4 7 93 7 2 9 4sortat descrescător:9 7 4 3 2
De ce avem nevoie de sortare?
- pentru a afișa un clasament (de la cel mai mare la cel mai mic);
- pentru a găsi mai ușor o valoare (căutarea binară funcționează doar pe vectori sortați);
- pentru a elimina duplicate mai eficient;
- pentru a rezolva multe probleme de concurs.
Metoda 1: Sortarea prin selecție (Selection Sort)
Ideea
La fiecare pas, căutăm cel mai mic element din partea nesortată și îl punem pe poziția corectă.
Algoritmul
- Parcurgem vectorul de la poziția
1lan. - Pentru fiecare poziție
i, căutăm minimul dinv[i], v[i+1], ..., v[n]. - Interschimbăm minimul găsit cu
v[i]. - Acum
v[i]conține valoarea corectă, trecem lai + 1.
Codul
#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
int v[1001];
int n;
int main()
{
fin >> n;
for (int i = 1; i <= n; i++) {
fin >> v[i];
}
for (int i = 1; i < n; i++) {
int pozMin = i;
for (int j = i + 1; j <= n; j++) {
if (v[j] < v[pozMin]) {
pozMin = j;
}
}
// Interschimbăm v[i] cu v[pozMin]
int aux = v[i];
v[i] = v[pozMin];
v[pozMin] = aux;
}
for (int i = 1; i <= n; i++) {
fout << v[i] << " ";
}
return 0;
}date.in:
5
3 7 2 9 4date.out:
2 3 4 7 9Pas cu pas
Vector inițial: 3 7 2 9 4
| Pas | i | Minim din restul | Interschimbare | Vector |
|---|---|---|---|---|
| 1 | 1 | 2 (poz 3) |
v[1] ↔︎ v[3] |
2 7 3 9 4 |
| 2 | 2 | 3 (poz 3) |
v[2] ↔︎ v[3] |
2 3 7 9 4 |
| 3 | 3 | 4 (poz 5) |
v[3] ↔︎ v[5] |
2 3 4 9 7 |
| 4 | 4 | 7 (poz 5) |
v[4] ↔︎ v[5] |
2 3 4 7 9 |
Interschimbarea a două valori necesită o
variabilă auxiliară aux. Fără ea, am pierde una
dintre valori.
Metoda 2: Sortarea prin metoda bulelor (Bubble Sort)
Ideea
Comparăm elemente vecine și le interschimbăm dacă sunt în ordine greșită. Repetăm până când vectorul este sortat.
La fiecare parcurgere, cel mai mare element „urcă” spre final, ca un balon (de aici numele).
Algoritmul
- Parcurgem vectorul și comparăm
v[i]cuv[i+1]. - Dacă
v[i] > v[i+1], le interschimbăm. - Repetăm parcurgerea până când nu mai facem nicio interschimbare.
Codul
#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
int v[1001];
int n;
int main()
{
fin >> n;
for (int i = 1; i <= n; i++) {
fin >> v[i];
}
int sortat = 0;
while (sortat == 0) {
sortat = 1;
for (int i = 1; i < n; i++) {
if (v[i] > v[i + 1]) {
int aux = v[i];
v[i] = v[i + 1];
v[i + 1] = aux;
sortat = 0;
}
}
}
for (int i = 1; i <= n; i++) {
fout << v[i] << " ";
}
return 0;
}date.in:
5
3 7 2 9 4date.out:
2 3 4 7 9Pas cu pas
Vector inițial: 3 7 2 9 4
Parcurgerea 1:
| Comparație | Acțiune | Vector |
|---|---|---|
3 vs 7 |
OK | 3 7 2 9 4 |
7 vs 2 |
Interschimbare | 3 2 7 9 4 |
7 vs 9 |
OK | 3 2 7 9 4 |
9 vs 4 |
Interschimbare | 3 2 7 4 9 |
Am făcut interschimbări → continuăm.
Parcurgerea 2:
| Comparație | Acțiune | Vector |
|---|---|---|
3 vs 2 |
Interschimbare | 2 3 7 4 9 |
3 vs 7 |
OK | 2 3 7 4 9 |
7 vs 4 |
Interschimbare | 2 3 4 7 9 |
7 vs 9 |
OK | 2 3 4 7 9 |
Am făcut interschimbări → continuăm.
Parcurgerea 3:
| Comparație | Acțiune | Vector |
|---|---|---|
2 vs 3 |
OK | 2 3 4 7 9 |
3 vs 4 |
OK | 2 3 4 7 9 |
4 vs 7 |
OK | 2 3 4 7 9 |
7 vs 9 |
OK | 2 3 4 7 9 |
Nicio interschimbare → vectorul este sortat!
Sortare descrescătoare
Pentru a sorta descrescător, inversăm condiția de comparare:
Selection Sort descrescător: căutăm maximul în loc de minim:
if (v[j] > v[pozMax]) {
pozMax = j;
}Bubble Sort descrescător: interschimbăm când
v[i] < v[i+1]:
if (v[i] < v[i + 1]) {
// interschimbăm
}Comparație între metode
| Selection Sort | Bubble Sort | |
|---|---|---|
| Idee | Selectează minimul, pune-l pe loc | Compară vecini, interschimbă |
| Nr. comparații | Mereu la fel | Poate termina mai devreme |
| Când e rapid | Similar pentru ambele | Mai rapid dacă vectorul e aproape sortat |
| Ușor de implementat | Da | Da |
Care e mai bun?
Ambele metode au aceeași complexitate în cel mai rău caz: fac
aproximativ n × n / 2 comparații.
Pentru vectori mici (până la câteva mii de elemente), ambele sunt suficient de rapide.
Pentru vectori foarte mari, există metode mult mai eficiente (Quick Sort, Merge Sort), dar acestea se studiază mai târziu.
Interschimbarea - operația de bază
Interschimbarea apare în orice algoritm de sortare. Forma standard:
int aux = v[i];
v[i] = v[j];
v[j] = aux;De ce avem nevoie de
aux?
Fără variabila auxiliară:
v[i] = v[j]; // am pierdut valoarea veche a lui v[i]!
v[j] = v[i]; // acum ambele au valoarea lui v[j]Cu aux, salvăm mai întâi valoarea veche:
aux = v[i]; // salvăm v[i]
v[i] = v[j]; // v[i] primește valoarea lui v[j]
v[j] = aux; // v[j] primește valoarea veche a lui v[i]Exemplu complet: sortare și afișare mediană
Mediana este elementul din mijlocul vectorului sortat.
#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
int v[1001];
int n;
int main()
{
fin >> n;
for (int i = 1; i <= n; i++) {
fin >> v[i];
}
// Sortăm crescător (Selection Sort)
for (int i = 1; i < n; i++) {
int pozMin = i;
for (int j = i + 1; j <= n; j++) {
if (v[j] < v[pozMin]) {
pozMin = j;
}
}
int aux = v[i];
v[i] = v[pozMin];
v[pozMin] = aux;
}
// Mediana
fout << v[(n + 1) / 2];
return 0;
}date.in:
5
3 7 2 9 4date.out:
4Vectorul sortat: 2 3 4 7 9. Elementul din mijloc
(poziția 3): 4.
Greșeli frecvente
1. Interschimbarea fără variabilă auxiliară
// GREȘIT:
v[i] = v[j];
v[j] = v[i]; // ambele au acum aceeași valoare!Folosește mereu aux.
2.
Bucla exterioară merge până la n în loc de
n - 1
La Selection Sort:
for (int i = 1; i < n; i++) { // < n, NU <= nUltimul element rămâne automat pe loc - nu trebuie procesat.
3. Bubble Sort fără condiție de oprire
// GREȘIT: face mereu n parcurgeri, chiar dacă e deja sortat
for (int pas = 1; pas < n; pas++) {
for (int i = 1; i < n; i++) {
// ...
}
}Varianta cu sortat (flag) se oprește imediat ce
nu mai sunt interschimbări.
4. Confuzia între sortare crescătoare și descrescătoare
- Crescător:
v[i] > v[i+1]→ interschimbăm (mutăm pe cel mare la dreapta) - Descrescător:
v[i] < v[i+1]→ interschimbăm (mutăm pe cel mic la dreapta)
Ce să reții
- Selection Sort: la fiecare pas, selectăm minimul din partea nesortată și îl punem pe loc.
- Bubble Sort: comparăm vecini și îi interschimbăm; repetăm până e sortat.
- Interschimbarea necesită variabilă
auxiliară (
aux). - Pentru sortare descrescătoare, inversăm condiția de comparare.
- Ambele metode sunt bune pentru vectori mici (sub câteva mii de elemente).
- La concursuri de clasa a V-a, oricare dintre cele două este acceptată.