- 1 1. Mis on kiirkorrastus? Põhimõisted ja ülevaade
- 2 2. Kiirkorrastuse algoritmi selgitus
- 3 3. Kiirkorrastuse teostus C-keeles
- 4 4. Kiirkorrastuse jõudlus ja optimeerimine
- 5 5. Kiirkorrastuse ja teiste sorteerimisalgoritmide võrdlus
- 6 6. Levinumad kiirkorrastuse vead ja tõrkeotsing
- 7 7. Kokkuvõte ja tulevased rakendused
1. Mis on kiirkorrastus? Põhimõisted ja ülevaade
Kiirkorrastus (QuickSort) on üks sorteerimisalgoritmidest, mida kasutatakse andmete tõhusaks järjestamiseks nii C-keeles kui ka paljudes teistes programmeerimiskeeltes. Selle algoritmi lõi C. A. R. Hoare ning selle põhieeliseks on väga kiire töökiirus.
Kiirkorrastuse põhiidee
Kiirkorrastus jagab andmed pivotiks nimetatud võrdlusaluse abil ning sorteerib neid rekursiivselt. Selle jaga ja valitse lähenemisega sorteerimisalgoritmiga saavutatakse lõpuks täielikult sorditud tulemused.
- Pivott: juhuslikult või teatud reegli järgi valitud väärtus, mille alusel andmed jagatakse kaheks grupiks.
- Jaga ja valitse: Probleemi lahendamine selle jagamisega väiksemateks alamprobleemideks, mida lahendatakse eraldi ning seejärel kombineeritakse tulemused.
Kiirkorrastus on võrreldes teiste sorteerimisalgoritmidega (näiteks mullisorteerimine või sisestussorteerimine) eriti suurte andmekogumite puhul väga kiire.
2. Kiirkorrastuse algoritmi selgitus
Järgmisena vaatame lähemalt, kuidas kiirkorrastuse algoritm töötab.
Pivoti valik
Kiirkorrastuse esimene samm on pivoti valimine massiivist. Pivot mõjutab oluliselt algoritmi kiirust ning selle valikust sõltub ka soorituse efektiivsus.
- Näide: Pivotiks võib valida massiivi esimese, viimase või keskmise elemendi.
Rekursiivne jagamine
Pärast pivoti valimist jagatakse massiiv kahte ossa: väiksemad väärtused ühele poole ja suuremad teisele poole pivotit. Seejärel korratakse sama protseduuri rekursiivselt ülejäänud osadega.
- Samm 1: Väiksemad elemendid liiguvad vasakule, suuremad paremale.
- Samm 2: Iga jagatud osa korral rakendatakse taas kiirkorrastust.
Selle rekursiivse jagamise tulemusena saab lõpuks kogu massiiv sorditud.
3. Kiirkorrastuse teostus C-keeles
Järgmiseks selgitame, kuidas kiirkorrastust C-keeles realiseerida. Allpool on toodud põhiline näidis C-koodist.
#include <stdio.h>
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // Valib viimase elemendi pivotiks
int i = (low - 1); // Väiksemate elementide indeks
for (int j = low; j <= high - 1; j++) {
if (arr[j] <= pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
// Rakenda rekursiivselt kiirkorrastust jagatud massiividele
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
int main() {
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, 0, n - 1);
printf("Sorted array:n");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("n"); // Lisa reavahetus
return 0;
}
Selles koodis vahetab swap-funktsioon kahe elemendi väärtusi, partition-funktsioon jagab massiivi pivoti alusel, ning quickSort-funktsioon sorteerib rekursiivselt kogu massiivi.

4. Kiirkorrastuse jõudlus ja optimeerimine
Kiirkorrastust peetakse väga kiireks sorteerimisalgoritmiks, kuid halvemal juhul võib jõudlus oluliselt langeda. Selles jaotises selgitame jõudlust ja optimeerimisvõtteid.
Ajaline keerukus ja halvim stsenaarium
Kiirkorrastuse keskmine ajaline keerukus on O(n log n), kuid halvimal juhul – näiteks juba sorditud või korduvate väärtustega massiivide korral – võib jõudlus olla O(n^2). Sellisel juhul suureneb rekursiooni sügavus ja efektiivsus langeb.
Optimeerimisvõtted
- Pivoti valiku optimeerimine: Valides pivotiks keskmise või juhusliku elemendi, mitte alati esimese või viimase, saavutatakse tasakaalustatud jaotus.
- Rekursiooni kontrollimine: Rekursiooni sügavuse vähendamiseks saab kasutada mitterekursiivseid lähenemisi.
5. Kiirkorrastuse ja teiste sorteerimisalgoritmide võrdlus
Kiirkorrastus on väga efektiivne, kuid olemas on ka teisi levinud sorteerimisviise. Selles jaotises võrdleme kiirkorrastust teiste algoritmidega, analüüsides nende tugevusi ja nõrkusi.
Kiirkorrastus vs. liitmiskorrastus
- Algoritmi olemus:
Nii kiirkorrastus kui ka liitmiskorrastus (MergeSort) kasutavad jaga ja valitse põhimõtet, kuid nende jagamise ja ühendamise viis on erinev. Kiirkorrastus keskendub jagamisele ja sorteerib iga osa iseseisvalt, liitmiskorrastus keskendub lõpuks sorted osade ühendamisele. - Jõudlus:
Mõlema algoritmi keskmine keerukus on O(n log n), kuid kiirkorrastuse halvim juht on O(n^2), samas kui liitmiskorrastusel püsib see O(n log n) juures, tagades stabiilse jõudluse. - Eelised ja puudused:
Kiirkorrastus vajab tavaliselt vähem lisa mälu kui liitmiskorrastus ja sobib suurte andmemahtude puhul, kuid võib olla haavatav halvimale stsenaariumile. Liitmiskorrastus on stabiilne ja töötab ühtlaselt ka juba peaaegu sorditud andmetega.
Kiirkorrastus vs. kuhjakorrastus
- Algoritmi olemus:
Kiirkorrastus töötab rekursiivselt massiivi jagades, kuhjakorrastus (HeapSort) teisendab andmed kuhjaks ja võtab välja maksimaalse (või minimaalse) väärtuse. - Jõudlus:
Kuhjakorrastus on samuti O(n log n), kuid tihti aeglasem kui kiirkorrastus, eriti mittejuhuslike andmete korral. - Eelised ja puudused:
Kiirkorrastus on tavalistel juhtudel kiirem, kuid kuhjakorrastus tagab alati O(n log n) jõudluse, pakkudes turvalisust halvimates olukordades.
Kiirkorrastus vs. mullisorteerimine
- Algoritmi olemus:
Mullisorteerimine (BubbleSort) on väga lihtne algoritm, mis võrdleb kõrvutisi elemente ja vahetab neid vajadusel, kuid on väga ebaefektiivne. - Jõudlus:
Mullisorteerimine on O(n^2), seega oluliselt aeglasem kui kiirkorrastus. See sobib vaid väikeste andmehulkade jaoks. - Eelised ja puudused:
Mullisorteerimine on lihtne ja arusaadav, kuid tegelikus kasutuses palju kehvem kui kiirkorrastus ja pole suurte andmete puhul soovitatav.
6. Levinumad kiirkorrastuse vead ja tõrkeotsing
Kiirkorrastuse rakendamisel või qsort()
kasutamisel võib ette tulla mitmeid vigu. Selles jaotises selgitame levinumaid vigu ja nende lahendusi.
1. Virna ületäitumine (Stack overflow)
Kuna kiirkorrastus põhineb rekursioonil, võib liiga sügavale minnes tekkida virna ületäitumine. Selle vältimiseks võib piirata rekursiooni maksimaalset sügavust või kasutada mitterekursiivset lahendust.
- Lahendus: Rekursiivse osa asendamine tsükliga aitab vähendada virna ületäitumise riski.
2. Lõputu tsükkel (Infinite loop)
Vigadega rekursioonis või pivoti valikus võib tekkida lõputu tsükkel. Seda juhtub tihti, kui pivot on valitud valesti või sorteerimise lõpp-tingimus pole õigesti määratud.
- Lahendus: Kontrolli, et pivoti valiku loogika ja sorteerimise lõpp-tingimus oleks õigesti rakendatud.
3. Mälu rikkumine
Kui kasutatakse massiive ja osutajaid (pointereid), võib juhtuda mälu rikkumine, näiteks ligipääs massiivi piiridest väljapoole.
- Lahendus: Veendu, et massiivi piire ei ületata ning rekursioon toimib korrektselt.
7. Kokkuvõte ja tulevased rakendused
Kiirkorrastus on C-keeles üks kõige efektiivsemaid sorteerimisalgoritme, eriti suurte andmemahtude puhul. Pivoti valiku ja jaga-valitse meetodiga saavutatakse kiire tulemus. Samuti saab kasutada standardraamatukogu qsort()
funktsiooni mugavaks sorteerimiseks.
Tulevikus kiirkorrastust kasutades tasub arvestada andmete suurust ja tüüpi, et valida parim pivot ja saavutada maksimaalne jõudlus. Vigade korral tasub üle vaadata rekursiooni ja mälu kasutamise loogika.
Loodan, et see artikkel aitas mõista kiirkorrastuse põhimõtteid ja rakendamist ning saad seda kasutada oma projektides.