GeeksforGeeks (Nederlands)

Net als Merge Sort is QuickSort een Divide and Conquer-algoritme. Het kiest een element als draaipunt en verdeelt de gegeven array rond het gekozen draaipunt. Er zijn veel verschillende versies van quickSort die pivot op verschillende manieren selecteren.

  1. Kies altijd het eerste element als draaipunt.
  2. Kies altijd het laatste element als draaipunt (hieronder geïmplementeerd)
  3. Kies een willekeurig element als draaipunt.
  4. Kies mediaan als draaipunt.

Het belangrijkste proces in quickSort is partition (). Doel van partities is, gegeven een array en een element x van array als draaipunt, zet x op de juiste positie in een gesorteerde array en zet alle kleinere elementen (kleiner dan x) voor x, en zet alle grotere elementen (groter dan x) erna X. Dit alles moet in lineaire tijd worden gedaan.

Pseudo-code voor recursieve QuickSort-functie:

Partitie-algoritme
Er kunnen veel manieren zijn om te partitioneren, de volgende pseudocode gebruikt de methode die in het CLRS-boek wordt gegeven. De logica is eenvoudig, we beginnen bij het meest linkse element en houden de index van kleinere (of gelijk aan) elementen bij als i. Als we tijdens het doorlopen een kleiner element vinden, wisselen we het huidige element met arr. Anders negeren we het huidige element.

Pseudocode voor partitie ()

Illustratie van partitie ():

Implementatie:
Hieronder volgen de implementaties van QuickSort:

Output:

Sorted array:1 5 7 8 9 10

Analyse van QuickSort
De tijd die QuickSort in het algemeen in beslag neemt, kan als volgt worden geschreven.

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

De eerste twee termen zijn voor twee recursieve aanroepen, de laatste term is voor het partitieproces. k is het aantal elementen dat kleiner is dan pivot.
De tijd die QuickSort nodig heeft, hangt af van de invoerarray en de partitiestrategie. Hieronder volgen drie gevallen.

Slechtste geval: het slechtste geval doet zich voor wanneer het partitieproces altijd het grootste of kleinste element als spil kiest. Als we de bovenstaande partitiestrategie bekijken waarbij het laatste element altijd als draaipunt wordt gekozen, zou het ergste geval zich voordoen wanneer de array al in oplopende of aflopende volgorde is gesorteerd. Hieronder volgt een herhaling voor het ergste geval.

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

De oplossing van bovenstaande herhaling is (n2).

Beste geval: het beste geval doet zich voor wanneer het partitieproces altijd de middelste element als spil. Hieronder volgt in het beste geval herhaling.

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

De oplossing van bovenstaande herhaling is (nLogn). Het kan worden opgelost met case 2 van Master Theorem.

Gemiddelde case:
Om gemiddelde case-analyse uit te voeren, moeten we alle mogelijke permutaties van de array in overweging nemen en de tijd berekenen die nodig is voor elke permutatie die niet ziet er eenvoudig uit.
We kunnen een idee krijgen van een gemiddeld geval door het geval te beschouwen waarin partitie O (n / 9) -elementen in de ene set plaatst en O (9n / 10) -elementen in een andere set. Hieronder volgt een herhaling voor deze zaak.

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

Oplossing van bovenstaande herhaling is ook O (nLogn)

Hoewel de moeilijkste tijdcomplexiteit van QuickSort O (n2) is, wat QuickSort is meer dan veel andere sorteeralgoritmen zoals Merge Sort en Heap Sort, QuickSort is in de praktijk sneller, omdat de binnenlus efficiënt kan worden geïmplementeerd op de meeste architecturen en in de meeste real-world data. QuickSort kan op verschillende manieren worden geïmplementeerd door de keuze van de pivot te wijzigen, zodat het ergste geval zelden voorkomt voor een bepaald type gegevens. Het samenvoegen wordt echter over het algemeen als beter beschouwd als de gegevens enorm zijn en zijn opgeslagen in externe opslag.

Is QuickSort stabiel?
De standaardimplementatie is niet stabiel. Elk sorteeralgoritme kan echter stabiel worden gemaakt door indexen als vergelijkingsparameter te beschouwen.
Is QuickSort in-place?
Volgens de brede definitie van in-place-algoritme kwalificeert het zich als een in-place sorteeralgoritme omdat het extra ruimte alleen voor het opslaan van recursieve functieaanroepen, maar niet voor het manipuleren van de invoer.

Hoe QuickSort voor gekoppelde lijsten te implementeren?
QuickSort op enkel gekoppelde lijsten
QuickSort op dubbel gekoppelde lijst

Kunnen we QuickSort iteratief implementeren?
Ja, raadpleeg Iterative Quick Sort.

Waarom heeft QuickSort de voorkeur boven MergeSort voor het sorteren van arrays
Quick Sort in zijn algemene vorm is een in-place sortering (dwz het vereist geen extra opslag), terwijl samenvoegen sorteren O (N) extra opslag vereist, waarbij N de array-grootte aangeeft, die vrij duur kan zijn. Het toewijzen en opnieuw toewijzen van de extra ruimte die wordt gebruikt voor het samenvoegen, verhoogt de looptijd van het algoritme. Als we de gemiddelde complexiteit vergelijken, zien we dat beide typen de gemiddelde complexiteit O (NlogN) hebben, maar de constanten verschillen. Voor arrays verliest het samenvoegen sorteren door het gebruik van extra O (N) opslagruimte.

De meeste praktische implementaties van Quick Sort gebruiken een willekeurige versie. De gerandomiseerde versie heeft de verwachte tijdcomplexiteit van O (nLogn).Het slechtste geval is ook mogelijk in de willekeurige versie, maar het slechtste geval komt niet voor voor een bepaald patroon (zoals een gesorteerde array) en willekeurig snel sorteren werkt in de praktijk goed.

Snel sorteren is ook een cache-vriendelijke sortering algoritme omdat het een goede referentielocatie heeft bij gebruik voor arrays.

Quick Sort is ook tail recursief, daarom worden tail call-optimalisaties uitgevoerd.

Waarom MergeSort de voorkeur heeft boven QuickSort voor Linked Lists ?
In het geval van gelinkte lijsten is het geval anders, voornamelijk vanwege verschillen in geheugentoewijzing van arrays en gelinkte lijsten. In tegenstelling tot arrays zijn gekoppelde lijstknooppunten mogelijk niet aangrenzend in het geheugen. In tegenstelling tot array kunnen we in de gekoppelde lijst items in het midden invoegen in O (1) extra spatie en O (1) tijd. Daarom kan een samenvoegbewerking of een samenvoegsortering worden geïmplementeerd zonder extra ruimte voor gekoppelde lijsten.

In arrays kunnen we willekeurige toegang krijgen omdat elementen continu in het geheugen zijn. Laten we zeggen dat we een geheel getal (4-byte) array A hebben en laat het adres van A x zijn, dan hebben we voor toegang tot A direct toegang tot het geheugen op (x + i * 4). In tegenstelling tot arrays kunnen we geen willekeurige toegang doen in de gekoppelde lijst. Quick Sort vereist veel van dit soort toegang. In de gekoppelde lijst om toegang te krijgen tot de ith index, moeten we elk knooppunt van het hoofd naar het ith knooppunt reizen, omdat we geen continu geheugenblok hebben. Daarom neemt de overhead toe voor snel sorteren. Samenvoegen sorteert gegevens opeenvolgend en de behoefte aan willekeurige toegang is laag.

Hoe QuickSort te optimaliseren zodat het in het ergste geval O (Log n) extra ruimte in beslag neemt?
Zie QuickSort Tail Call Optimization (Slechtste ruimte verkleinen tot log n)

Snapshots:

  • Quiz op QuickSort
  • Recente artikelen over QuickSort
  • Codeeroefening voor sorteren.

Andere sorteeralgoritmen op GeeksforGeeks / GeeksQuiz:
Selectie sorteren, bellen sorteren, invoegen sorteren, samenvoegen sorteren, heap sorteren, QuickSort , Radix sorteren, tellen sorteren, emmers sorteren, schelpen sorteren, kam sorteren, duivengaten sorteren

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *