edubun
Nederlands

Sorteren 2: mergesort en quicksort

Een miljoen waarden sorteren door elk paar te vergelijken kost ongeveer 500 miljard vergelijkingen; mergesort heeft er ongeveer 20 miljoen nodig.

Splits het probleem en los de helften op

De methoden uit het vorige hoofdstuk werken op de hele lijst tegelijk en betalen daarvoor ongeveer n² vergelijkingen. De twee methoden hier gebruiken een ander plan, verdeel en heers. Splits de lijst in kleinere delen, sorteer elk deel met dezelfde methode en combineer de gesorteerde delen. Het splitsen gaat door tot een deel één waarde of geen heeft; een lijst van één waarde is al gesorteerd. Omdat de methode zichzelf aanroept op kleinere lijsten, is zij recursief (in hoofdstuk 6 bekijk je recursie in detail).

Mergesort: het werk zit in het samenvoegen

Mergesort deelt de lijst doormidden, sorteert de linkerhelft, sorteert de rechterhelft en voegt beide gesorteerde helften samen. Het slimme deel is het samenvoegen. Twee gesorteerde lijsten kun je combineren door alleen hun voorste waarden te bekijken. Vergelijk die, schrijf de kleinste op en schuif daar voorbij. Herhaal tot één lijst leeg is en kopieer dan de rest van de andere. [1, 4, 7] en [2, 3, 8] samenvoegen gaat als 1 (1 tegenover 2), 2 (4 tegenover 2), 3 (4 tegenover 3), 4 (4 tegenover 8), 7 (7 tegenover 8), waarna 8 wordt gekopieerd: 5 vergelijkingen voor 6 waarden. Twee lijsten met samen n waarden samenvoegen kost nooit meer dan n − 1 vergelijkingen.

function merge(left, right) {
  const out = [];
  let i = 0, j = 0;
  while (i < left.length && j < right.length) {
    if (right[j] < left[i]) out.push(right[j++]);
    else out.push(left[i++]);
  }
  return out.concat(left.slice(i), right.slice(j));
}

function mergeSort(a) {
  if (a.length <= 1) return a;          // already sorted
  const mid = Math.floor(a.length / 2);
  return merge(mergeSort(a.slice(0, mid)), mergeSort(a.slice(mid)));
}

Waarom is dit snel? Stel je het halveren voor als niveaus. Een lijst van 8 waarden splitst in 2 lijsten van 4, dan 4 lijsten van 2 en dan 8 lijsten van 1: drie niveaus, want 8 kan 3 keer worden gehalveerd. Op elk niveau raken alle samenvoegingen samen elke waarde eenmaal, dus een niveau kost hoogstens ongeveer n vergelijkingen. Met log₂ n niveaus is het totaal ongeveer n log₂ n. Voor een miljoen waarden zijn dat ongeveer 20 miljoen vergelijkingen, tegenover ongeveer 500 miljard voor de methoden die elk paar vergelijken. Gesplitst als [38, 27, 43, 3] en [9, 82, 10], zoals in het lab, kost [38, 27, 43, 3, 9, 82, 10] 14 vergelijkingen; de code hierboven splitst in 3 en 4 en kost 13.

De prijs is geheugen. Samenvoegen vraagt een plek om de uitvoer te schrijven, dus mergesort gebruikt een tweede lijst zo groot als de invoer. Mergesort is ook stabiel: waarden die gelijk vergelijken behouden hun oorspronkelijke volgorde, omdat bij gelijke voorste waarden de linker wordt genomen. Dat is belangrijk als je een tabel achtereenvolgens op verschillende kolommen sorteert, bijvoorbeeld op stad en dan op naam.

Laden

Sleep om te draaien. Scroll of knijp om te zoomen.

Bij mergesort zie je welk deel wordt samengevoegd; bij quicksort is de spil paars. Verhoog het aantal waarden naar 40 en vergelijk de tellers met insertionsort.

Quicksort: splits rond een spil

Quicksort verdeelt de lijst anders. Het kiest één waarde, de spil, en herschikt de lijst zodat alles kleiner dan de spil ervoor komt en de rest erna. Deze stap heet partitioneren. De spil staat nu definitief goed en beide kanten kun je afzonderlijk met dezelfde methode sorteren. Achteraf samenvoegen is niet nodig, omdat elke waarde links al kleiner is dan elke waarde rechts.

In het lab gebruik je een gangbare leerboekversie die de laatste waarde van elk deel als spil neemt. Op [5, 1, 4, 2, 8] wordt spil 8 met de vier andere, kleinere waarden vergeleken, dus 8 blijft achteraan. Het volgende deel [5, 1, 4, 2] gebruikt spil 2: alleen 1 is kleiner, dus na twee verwisselingen is de lijst [1, 2, 4, 5, 8]. Nog één vergelijking verwerkt [4, 5]. Totaal: 8 vergelijkingen en 2 verwisselingen.

Als de spil dicht bij het midden uitkomt, halveert elke splitsing het probleem en kost quicksort ongeveer n log₂ n vergelijkingen, net als mergesort. Het werkt ook binnen de oorspronkelijke lijst zonder tweede kopie. Maar een slechte spil schaadt. Als de lijst al gesorteerd is en de spil altijd de laatste waarde, haalt elke splitsing slechts één waarde weg en valt quicksort terug op ongeveer n²/2 vergelijkingen: 10 voor [1, 2, 3, 4, 5], hetzelfde als selectionsort. Echte bibliotheken vermijden dit door de spil zorgvuldiger te kiezen, bijvoorbeeld willekeurig of als middelste van drie steekproefwaarden.

AchtergrondBeide methoden hebben een bekende oorsprong. John von Neumann stelde mergesort voor in 1945, toen de eerste computers met opgeslagen programma's werden ontworpen. Quicksort kwam van Tony Hoare, een Britse student aan de Staatsuniversiteit van Moskou in 1959. Hij kreeg werk aangeboden aan automatische vertaling van Russisch naar Engels. Omdat het woordenboek op magneetband stond, moesten de woorden van elke zin eerst alfabetisch worden geordend. Zijn eerste idee kostte tijd evenredig met het kwadraat van de zinslengte; zijn tweede werd quicksort. Hij publiceerde het in 1961.
MethodeVergelijkingenExtra geheugen
Insertionsortgebruikelijk ongeveer n²/4, slechtste geval ongeveer n²/2geen; stabiel
Mergesortaltijd ongeveer n log₂ neen tweede lijst van n waarden; stabiel
Quicksortgebruikelijk ongeveer n log₂ n, slechtste geval ongeveer n²/2 (slechte spillen)weinig; gebruikelijke versies niet stabiel
Kan een vergelijkingssorteermethode beter zijn dan n log₂ n? Nee. Een methode die alleen leert door paren te vergelijken moet alle n! mogelijke beginvolgorden kunnen onderscheiden. Elke vergelijking heeft twee uitkomsten, dus het slechtste geval vraagt minstens log₂(n!) vergelijkingen, wat groeit als n log₂ n. Voor 10 waarden is die grens 22 vergelijkingen.
verdeel en heersSplits een probleem, los de delen op dezelfde manier op en combineer de resultaten
samenvoegenCombineer twee gesorteerde lijsten door steeds de kleinste voorste waarde te nemen
mergesortHalveer, sorteer elke helft, voeg samen: ongeveer n log₂ n vergelijkingen
spilDe waarde waar quicksort de lijst omheen splitst
partitionerenHerschikken zodat kleinere waarden vóór de spil staan en de rest erna
quicksortPartitioneer rond een spil en sorteer dan elke kant
stabiele sorteringGelijke waarden behouden hun oorspronkelijke volgorde
ter plekkeSorteert binnen de oorspronkelijke lijst met weinig extra geheugen
  1. Hoeveel vergelijkingen kost het om [1, 4, 7] en [2, 3, 8] samen te voegen?
  2. Hoeveel vergelijkingen kost het om [1, 2, 3] en [4, 5, 6] samen te voegen?
  3. Een lijst van 16 waarden wordt gehalveerd totdat elk deel één waarde heeft. Hoeveel halveringsniveaus zijn er?
  4. Hoeveel vergelijkingen doet mergesort ongeveer op een miljoen waarden?
    • ongeveer 20
    • ongeveer 20 miljoen
    • ongeveer 500 miljard
    • precies één miljoen
  5. Waar staat de spil na het partitioneren?
    • Op de definitieve gesorteerde positie
    • Vooraan
    • Achteraan
    • Ergens; hij beweegt later opnieuw
  6. Quicksort met de laatste waarde als spil werkt op de al gesorteerde lijst [1, 2, 3, 4, 5]. Hoeveel vergelijkingen doet het?
  7. Welke methode heeft een tweede lijst zo groot als de invoer nodig?
    • Mergesort
    • Quicksort
    • Insertionsort
  8. Wie stelde mergesort in 1945 voor?
    • Tony Hoare
    • John von Neumann
    • Ada Lovelace
    • Euclides
  9. Welk probleem bracht Tony Hoare tot quicksort?
    • Woorden van een zin sorteren voor een woordenboek op magneetband
    • Bibliotheekboeken sorteren
    • Webpagina's rangschikken
    • Bankcheques sorteren
  10. Waarom heet mergesort stabiel?
    • Gelijke waarden behouden hun oorspronkelijke volgorde
    • Het loopt nooit vast
    • Het kost altijd evenveel tijd
    • Het gebruikt geen extra geheugen
  11. Wat is het kleinste mogelijke maximale aantal vergelijkingen voor een vergelijkingssorteermethode op 10 waarden (log₂ 10!, naar boven afgerond)?
Belangrijkste punten
  • Verdeel en heers: splits, los de delen op, combineer.
  • Mergesort: altijd ongeveer n log₂ n vergelijkingen, extra geheugen nodig, stabiel.
  • Quicksort: partitioneer rond een spil; gemiddeld snel, ongeveer n²/2 met slechte spillen.
  • Een miljoen waarden: ongeveer 20 miljoen vergelijkingen in plaats van 500 miljard.
  • Geen vergelijkingssorteermethode kan in het slechtste geval beter dan ongeveer n log₂ n.
Bronnen van deze cursus (11)
  • MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon)
  • lecture notes 1 Introduction, 3 Sorting, 9 Breadth-First Search, 10 Depth-First Search (ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes) and Fall 2011 lecture 13 BFS notes (ocw.mit.edu/courses/6-006-introduction-to-algorithms-fall-2011)
  • Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (MIT Press)
  • with the CLRS-based Khan Academy algorithms unit by Thomas Cormen and Devin Balkcom of Dartmouth (khanacademy.org/computing/computer-science/algorithms: binary search, selection sort analysis, merge sort, quicksort overview and analysis)
  • MacTutor History of Mathematics, Al-Khwarizmi (mathshistory.st-andrews.ac.uk/Biographies/Al-Khwarizmi: word algorithm from the Latin title Algoritmi de numero Indorum)
  • D. E. Joyce, Euclid's Elements Book VII Propositions 1 and 2 (mathcs.clarku.edu/~djoyce/elements/bookVII)
  • Wolfram MathWorld, Merge Sort (mathworld.wolfram.com/MergeSort.html: proposed by John von Neumann in 1945, after Knuth 1998 p. 159)
  • Stanford CS "Tony Hoare: Quicksort" (cs.stanford.edu/people/eroberts/courses/soco/projects/2008-09/tony-hoare/quicksort.html: devised while a student at Moscow State University for Russian-English machine translation with a tape dictionary, programmed in Algol 60 and published 1961; the year 1959 from the Wikipedia Quicksort article and its cited sources)
  • Bodleian Libraries, Ada Lovelace (blogs.bodleian.ox.ac.uk/adalovelace: 1843 paper, Note G Bernoulli numbers)
  • Fourmilab text of Menabrea's Sketch with Lovelace's notes (fourmilab.ch/babbage/sketch.html)
  • Seven Bridges of Konigsberg (Euler 1736) and Tower of Hanoi (Edouard Lucas, 1883) checked against the Wikipedia articles and their cited sources.

Geraadpleegd: 2026-10-17