GeeksforGeeks (Română)

La fel ca Merge Sort, QuickSort este un algoritm Divide and Conquer. Acesta alege un element ca pivot și partiționează matricea dată în jurul pivotului ales. Există multe versiuni diferite de quickSort care aleg pivot în moduri diferite.

  1. Alegeți întotdeauna primul element ca pivot.
  2. Alegeți întotdeauna ultimul element ca pivot (implementat mai jos)
  3. Alegeți un element aleatoriu ca pivot.
  4. Alegeți mediana ca pivot.

Procesul cheie în quickSort este partiția (). Ținta partițiilor este, având în vedere o matrice și un element x de matrice ca pivot, pune x în poziția sa corectă în matrice sortată și pune toate elementele mai mici (mai mici decât x) înainte de x și pune toate elementele mai mari (mai mari decât x) după X. Toate acestea trebuie făcute în timp liniar.

Cod pseudo pentru funcția recursivă QuickSort:

Algoritmul partiției
Există mai multe modalități de a face partiția, după pseudo cod adoptă metoda dată în cartea CLRS. Logica este simplă, pornim de la elementul din stânga și urmărim indexul elementelor mai mici (sau egale cu) ca i. În timp ce traversăm, dacă găsim un element mai mic, schimbăm elementul curent cu arr. În caz contrar, ignorăm elementul curent.

Pseudo cod pentru partiție ()

Ilustrația partiției ():

Implementare:
Următoarele sunt implementările QuickSort:

Ieșire:

Sorted array:1 5 7 8 9 10

Analiza QuickSort
Timpul luat de QuickSort în general poate fi scris după cum urmează.

 T(n) = T(k) + T(n-k-1) + (n)

Primii doi termeni sunt pentru două apeluri recursive, ultimul termen este pentru procesul de partiție. k este numărul de elemente mai mici decât pivotul.
Timpul luat de QuickSort depinde de matricea de intrare și de strategia de partiție. Următoarele sunt trei cazuri.

Cel mai rău caz: cel mai rău caz apare atunci când procesul de partiție alege întotdeauna cel mai mare sau cel mai mic element ca pivot. Dacă luăm în considerare strategia de partiție de mai sus, unde ultimul element este întotdeauna ales ca pivot, cel mai rău caz ar apărea atunci când matricea este deja sortată în ordine crescătoare sau descrescătoare. Urmează recurența în cel mai rău caz.

 T(n) = T(0) + T(n-1) + (n)which is equivalent to T(n) = T(n-1) + (n)

Soluția recurenței de mai sus este (n2).

Cel mai bun caz: cel mai bun caz apare atunci când procesul de partiție alege întotdeauna element de mijloc ca pivot. Urmează recurența pentru cel mai bun caz.

 T(n) = 2T(n/2) + (n)

Soluția recurenței de mai sus este (nLogn). Poate fi rezolvat folosind cazul 2 din Master Theorem.

Caz mediu:
Pentru a face o analiză medie a cazurilor, trebuie să luăm în considerare toate permutările posibile ale matricei și să calculăm timpul luat de fiecare permutare care nu arată ușor.
Ne putem face o idee despre caz mediu luând în considerare cazul când partiția pune elemente O (n / 9) într-un set și elemente O (9n / 10) în alt set. Urmează recurența pentru acest caz.

 T(n) = T(n/9) + T(9n/10) + (n)

Soluția recurenței de mai sus este, de asemenea, O (nLogn)

Deși complexitatea timpului cel mai rău în QuickSort este O (n2) care este mai mult decât mulți alți algoritmi de sortare precum Merge Sort și Heap Sort, QuickSort este mai rapid în practică, deoarece bucla sa interioară poate fi implementată eficient pe majoritatea arhitecturilor și în majoritatea datelor din lumea reală. QuickSort poate fi implementat în moduri diferite prin schimbarea alegerii pivotului, astfel încât cel mai rău caz apare rar pentru un anumit tip de date. Cu toate acestea, sortarea de îmbinare este considerată, în general, mai bună atunci când datele sunt imense și sunt stocate în stocare externă.

Este QuickSort stabil?
Implementarea implicită nu este stabilă. Cu toate acestea, orice algoritm de sortare poate fi stabilizat considerând indicii ca parametru de comparație.
Este QuickSort în loc?
Conform definiției largi a algoritmului în loc, acesta se califică ca un algoritm de sortare în loc, deoarece folosește suplimentar spațiu numai pentru stocarea apelurilor de funcții recursive, dar nu și pentru manipularea intrării.

Cum se implementează QuickSort pentru listele conectate?
QuickSort pe lista cu legături individuale
QuickSort pe o listă dublă legată

Putem implementa QuickSort în mod iterativ?
Da, vă rugăm să consultați Sortarea rapidă iterativă.

De ce este preferată Sortarea rapidă decât MergeSort pentru sortarea matricelor
Sortare rapidă în forma sa generală este o sortare la locul (adică nu necesită stocare suplimentară) în timp ce sortarea combinată necesită stocare suplimentară O (N), N denotând dimensiunea matricei care poate fi destul de costisitoare. Alocarea și delocarea spațiului suplimentar utilizat pentru sortarea îmbinării mărește timpul de funcționare al algoritmului. Comparând complexitatea medie, constatăm că ambele tipuri de sorturi au O (NlogN) complexitate medie, dar constantele diferă. Pentru tablouri, sortarea îmbinării pierde datorită utilizării spațiului de stocare suplimentar O (N).

Majoritatea implementărilor practice ale Sortării rapide utilizează versiunea randomizată. Versiunea randomizată a așteptat complexitatea timpului O (nLogn).Cel mai rău caz este posibil și în versiunea randomizată, dar cel mai rău caz nu apare pentru un anumit model (cum ar fi matricea sortată) și Sortarea rapidă randomizată funcționează bine în practică.

Sortarea rapidă este, de asemenea, o sortare prietenoasă cu memoria cache algoritm, deoarece are o localitate bună de referință atunci când este utilizat pentru matrici.

Sortarea rapidă este, de asemenea, recursivă la coadă, de aceea se fac optimizări ale apelurilor la coadă.

De ce MergeSort este preferat peste QuickSort pentru listele conectate ?
În cazul listelor conectate, cazul este diferit în principal din cauza diferenței în alocarea de memorie a matricelor și a listelor legate. Spre deosebire de matrice, este posibil ca nodurile listelor legate să nu fie adiacente în memorie. Spre deosebire de matrice, în lista legată, putem insera elemente în mijloc în O (1) spațiu suplimentar și O (1) timp. Prin urmare, operația de îmbinare de sortare de îmbinare poate fi implementată fără spațiu suplimentar pentru listele legate.

În tablouri, putem face acces aleatoriu, deoarece elementele sunt continue în memorie. Să spunem că avem o matrice întreagă (4 octeți) A și lăsăm adresa lui A să fie x apoi pentru a accesa A, putem accesa direct memoria la (x + i * 4). Spre deosebire de tablouri, nu putem face acces aleatoriu în lista legată. Sortarea rapidă necesită mult de acest tip de acces. În lista legată pentru a accesa indexul i, trebuie să călătorim fiecare nod de la cap la nodul i’th, deoarece nu avem un bloc continuu de memorie. Prin urmare, cheltuielile generale cresc pentru sortare rapidă. Merge sort accesează datele secvențial și nevoia de acces aleator este redusă.

Cum se optimizează QuickSort astfel încât să ia O (Log n) spațiu suplimentar în cel mai rău caz?
Vă rugăm să consultați QuickSort Tail Call Optimization (Reducerea spațiului cel mai rău caz la Log n)

Instantanee:

  • Test pe QuickSort
  • Articole recente despre QuickSort
  • Practică de codare pentru sortare.

Alte algoritmi de sortare pe GeeksforGeeks / GeeksQuiz: Sortare selectare
, Sortare cu bule, Sortare prin inserție, Sortare Merge, Sortare Heap, QuickSort , Sortare Radix, Sortare numărare, Sortare cupă, ShellSort, Sortare pe pieptene, Sortare porumbel

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *