2.2 Flettesortering

I dette afsnit betragter vi algoritmer, hvis grundlæggende operation er fletning: Vi fletter to ordnede sekvenser sammen til én stor ordnet sekvens. Denne operation giver anledning til en enkel rekursiv metode kaldet flettesortering: En række kan sorteres ved at rekursivt sortere hver halvdel for sig og derefter flette resultaterne.

Mergesort
Flettesortering sorterer en række med \(N\) elementer i tid proportional med \( N\log N\) i værste fald. Flettersorterings primære ulempe er, at den bruger ekstra plads af samme størrelsesorden som \( N\).

Abstrakt fletning på plads.

Flettemetoden merge(a, lo, mid, hi) i programmet Merge.java lægger resultatet af fletningen af delrækkerne a[lo..mid] og a[mid+1..hi] i én ordnet række a[lo..hi]. Det kunne være ønskværdigt at gennemføre denne proces uden at bruge for meget ekstra plads, men sådanne løsninger er overordentligt komplicerede. I stedet kopierer metoden merge() alting ind en hjælperække under fletningen og flytter siden resultatet tilbage til den oprindelige række.

Mergesort

Rekursiv flettesortering (oppefra og ned).

Programmet Merge.java implementerer rekursiv flettesorting ved brug af den abstrakte fletning på plads. Det er et af de bedst kendte eksemper på anvendelsen af del og hersk-paradigmet til konstruktion af effektive algoritmer.

Mergesort

Påstand.

Flettesortering oppefra og ned bruger mellem \(\frac{1}{2} N\operatorname{lg} N\) og \( N\operatorname{lg} N\) sammenligninger og højst \(6 N\operatorname{lg} N\) rækkeadgange for at sortere en række af længde \(N\).

Forbedringer.

Vi kan nedbringe køretiden for flettesortering betydeligt ved hjælp af nogle sindrige modifikationer af implementationen. Alle disse forbedringer er implementeret i programmet MergeX.java.

Visualisering.

Programmet MergeBars.java visualiserer opførslen af flettesortering med afskæring for små delrækker.

Mergesort visualization

Iterativ flettesortering (nedefra og op).

Selvom vi tænker på flettesortering som en metode til at sortere store rækker, bliver det meste af tiden under processen brugt til at flette meget korte delrækker. Men det udgangspunkt giver det mening at vende implementationen af flettesortering på hovedet: Først færdiggør vi alle fletninger af rækker af længde 1, som jo ellers ville blive udført, hver gang rekursionen når bunden. Dette skaber \(N/2\) sorterede delrækker af længde 2. I næste gennemløb fletter vi disse delrækker parvist til \(N/4\) sorterede delrækker af længde 4, og så videre indtil vi til sidste fletter hele rækken. Denne metode kan implementeres med endnu mindre kode en den rekursive implementation. Programmet MergeBU.java implementerer iterativ flettesortering.

Bottom-up
mergesort

Påstand.

Iterativ flettesortering bruger i værste fald mellem \(\frac{1}{2} N \operatorname{lg} N\) and \(N\operatorname{lg} N\) sammenligninger og højst \(6N\operatorname{lg} N\) rækkeopslag for at sortere en række af længde \(N\).

Påstand.

Ingen sammenligningsbaseret algoritme kan sortere \(N\) elementer med færre end \(\operatorname\{lg}(N!) \sim N \operatorname{lg} N\) sammenligninger i værste fald.

Påstand.

Flettesortering er en asymptotisk optimal sammenligningsbaseret sorteringsalgoritme. Der gælder at antallet af sammenligninger ved flettesortering i værste fald og det minimale antal sammenligninger af nogen sammenligningsbaseret sorteringsalgoritme er \(\sim N \operatorname{lg} N\).