Quicksort-algoritmi – tehokas jakopohjainen lajittelumenetelmä
Quicksort-algoritmi: tehokas jakopohjainen lajittelumenetelmä, nopea keskipistejakoon perustuva vertailulajittelu sekä käytännön optimoinnit ja suorituskykyvertailut.
Quicksort on lajittelualgoritmi, jota käytetään joukon elementtien lajitteluun. Sen loi Tony Hoare vuonna 1959, ja sitä käytetään edelleen laajalti. Quicksort-algoritmi luo osioita matriisiin, mikä tarkoittaa sitä, että se jakaa matriisin kahteen osaan ja jatkaa sitten näiden osien jakamista useampiin osiin ja lajittelua matkan varrella. Se tekee varsinaisen lajittelun, koska se on luonteeltaan vertailulajittelu. Tämä tarkoittaa sitä, että se valitsee sarjan keskipisteen ja vertaa sitä sitten kaikkiin muihin sarjan pisteisiin.
Miten Quicksort toimii
Quicksort perustuu jakoon (partitioning) ja rekursioon. Perusajatuksena on valita joukosta niin kutsuttu pivot-alkio ja järjestää muut alkio(t) siten, että kaikki pivotia pienemmät alkio(t) ovat pivotin vasemmalla puolella ja pivotia suuremmat oikealla. Tämän jälkeen sama toistetaan erikseen vasemmalle ja oikealle osajoukolle, kunnes osajoukot ovat yksittäisiä alkioita tai tyhjiä.
Jakamisen (partition) vaiheet lyhyesti
- Valitse pivot (esim. ensimmäinen, viimeinen, satunnainen tai median-of-three).
- Käy läpi osa taulukosta ja sijoittele alkioita niin, että vasemmalla ovat pienemmät ja oikealla suuremmat kuin pivot.
- Aloita rekursiivinen Quicksort vasemmalle ja oikealle osajoukolle.
Partition-toteutukset
Yleisimmät partition-menetelmät ovat Hoaren ja Lomuto-schemet. Hoarenin partition on usein hieman tehokkaampi ja vähemmän vaihtoja tekevä, Lomuton toteutus on yksinkertaisempi ymmärtää mutta tekee enemmän vaihtoja tietyissä tilanteissa.
Aikavaativuus ja muisti
- Keskiarvoinen aikavaativuus: O(n log n).
- Parhaimmillaan: O(n log n) (kun jakautuminen on tasapainoista).
- Pahimmillaan: O(n^2) (esimerkiksi, kun pivot valitaan huonosti ja taulukko on jo lajiteltu tai lähes lajiteltu).
- Tilavaativuus: tyypillisesti in-place, eli lisätilaa tarvitaan vain rekursion pinoon — odotusarvoisesti O(log n), pahimmillaan O(n).
Muita ominaisuuksia ja optimointeja
- Quicksort ei ole vakioisesti stabiili (saman avaimen elementtien alkuperäistä järjestystä ei välttämättä säilytetä).
- Pivotin valinta on kriittinen; yleisiä strategioita ovat satunnainen pivot, ensimmäinen/viimeinen alkio, sekä median-of-three (esim. kolme keskimmäistä arvoa).
- Satunnainen pivot auttaa välttämään pahimman tapauksen käytännössä.
- 3-way partitioning (Dutch national flag) on hyödyllinen, kun taulukossa on paljon samoja arvoja — se jakaa alueet vähemmän, yhtä ja suurempi kuin pivot.
- Pienillä osajoukoilla usein vaihdetaan tehokkaampaan insertion sort -menetelmään.
- Tail recursion -optimointi ja iteratiiviset versiot vähentävät rekursion pinoa.
- Monissa tuotantokirjastoissa käytetään hybridimenetelmiä, esimerkiksi introsort, joka vaihtaa Quicksortista Heapsortiin, jos rekursion syvyys kasvaa liian suureksi — näin taataan O(n log n) pahimmassa tapauksessa.
Missä Quicksort sopii ja mihin ei
Quicksort on usein nopea ja muistitehokas valinta taulukkorakenteille ja yleiskäyttöisille lajitteluoperaatioille. Se sopii erityisen hyvin silloin, kun keskimääräinen suoritusteho on tärkein tekijä ja kun stabiilisuus ei ole vaatimus. Jos stabiilisuus on pakollista tai jos halutaan varma O(n log n) pahin tapaus ilman hybridiratkaisuja, kannattaa harkita esimerkiksi Mergesort- tai Heapsort-algoritmeja.
Käytännön vinkkejä
- Käytä satunnaista pivot-valintaa tai median-of-three-strategiaa välttääksesi huonot tapaukset.
- Sekäota pienet osajoukot insertion sortilla.
- Jos data sisältää paljon samanarvoisia alkioita, käytä 3-way partitioningia.
- Hyödynnä bibliotekin valmis sort-funktioita (monet kirjastot käyttävät optimoituja hybridimenetelmiä).
Quicksort on yksinkertaisuudestaan huolimatta erittäin tehokas ja monipuolinen lajittelualgoritmi, ja sen optimoinnit tekevät siitä usein käytännössä nopeimman vaihtoehdon useissa tilanteissa.

Animoitu visualisointi quicksort-algoritmista. Vaakasuorat viivat ovat pivot-arvoja
Algoritmi
- Valitse mikä tahansa elementti joukosta, tämä on nyt nivelpiste.
- Jaottele elementit. Vertaile kaikkia matriisin elementtejä nivelpisteeseen, nivelpistettä alempana olevat elementit siirretään nivelpisteen vasemmalle puolelle ja kaikki nivelpistettä ylempänä olevat matriisin elementit siirretään nivelpisteen oikealle puolelle. Huomaa, että pivot on nyt lajitellussa asennossaan.
- Etsi uudelleen kaksi osiota. Sovelletaan edellä mainittuja kahta vaihetta vaiheessa 2 luotuihin kahteen osioon.
Usein niveleksi valitaan vasemmanpuoleisin elementti. Rekursio tarkoittaa, että algoritmi suorittaa täsmälleen saman algoritmin kahdelle osiolle, jotka on luotu vertailemalla pivot-elementtiin. Huomaa, että tämä algoritmi jatkaa matriisin jakamista osajoukkoihin ja näiden osajoukkojen jakamista vielä pienempiin osajoukkoihin. Joka kerta kun se tekee näin, se valitsee uuden pivot-arvon alajoukon sisällä ja vertaa elementtejä alajoukkoon. Perustapaus on, kun algoritmi saavuttaa alaruudun, jossa on vain yksi elementti, jolloin se vain pysähtyy, koska yhtä elementtiä ei tarvitse lajitella.
Etsiä