Tommy Färnqvist, IDA, Linköpings universitet. 1 Sortering Heap-sort Merge-sort Sammanfattning... 10

Relevanta dokument
Tommy Färnqvist, IDA, Linköpings universitet

Magnus Nielsen, IDA, Linköpings universitet

TDDI16 Datastrukturer och algoritmer. Prioritetsköer, heapar, Union/Find

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 9 Jonas Lindgren, Institutionen för Datavetenskap, LiU

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 10 Erik Nilsson, Institutionen för Datavetenskap, LiU

Föreläsning 4 Datastrukturer (DAT037)

Algoritmer, datastrukturer och komplexitet

Föreläsning 11 Datastrukturer (DAT037)

Algoritmer, datastrukturer och komplexitet

Föreläsning 9. Sortering

Sökning och sortering

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 6 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Föreläsning 10 Innehåll. Prioritetsköer och heapar. ADT Prioritetskö. Interface för Prioritetskö. Exempel på vad du ska kunna

Några svar till TDDC70/91 Datastrukturer och algoritmer

Föreläsning 5 Datastrukturer (DAT037)

Lösningsförslag för tentamen i Datastrukturer (DAT037) från

Föreläsning 4 Datastrukturer (DAT037)

Tentamen med lösningsförslag Datastrukturer för D2 DAT 035

ADT Prioritetskö. Föreläsning 13 Innehåll. Prioritetskö vs FIFO-kö. Prioritetskö Exempel på användning. Prioritetsköer och heapar

Föreläsning Datastrukturer (DAT037)

Datastrukturer. Föreläsning 5. Maps 1

Tommy Färnqvist, IDA, Linköpings universitet. 1 ADT Map/Dictionary Definitioner Implementation... 2

Algoritmanalys. Inledning. Informationsteknologi Malin Källén, Tom Smedsaas 1 september 2016

Seminarium 13 Innehåll

Föreläsning 13 Innehåll

Föreläsning Datastrukturer (DAT036)

Programmering för språkteknologer II, HT2014. Rum

ADT Prioritetskö. Föreläsning 12 Innehåll. Prioritetskö. Interface för Prioritetskö. Prioritetsköer och heapar

Föreläsning 2. AVL-träd, Multi-Way -sökträd, B-träd TDDD71: DALG. Innehåll. Innehåll. 1 Binära sökträd

Prov i DAT 312: Algoritmer och datastrukturer för systemvetare

Datastrukturer, algoritmer och programkonstruktion (DVA104, HT 2014) Föreläsning 5

DD1320 Tillämpad datalogi. Lösning (skiss) till tenta 20 okt 2011

Träd Hierarkiska strukturer

Föreläsning 5 TDDC91,TDDE22,725G97: DALG. Föreläsning i Datastrukturer och algoritmer 18 september 2018

Vad har vi pratat om i kursen?

Lösningar Datastrukturer TDA

Föreläsning 9 Datastrukturer (DAT037)

Föreläsning Datastrukturer (DAT037)

TDDI16 Datastrukturer och algoritmer. Algoritmanalys

Tentamen Datastrukturer för D2 DAT 035

Föreläsning 11 Innehåll

Teoretisk del. Facit Tentamen TDDC (6)

Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6

Föreläsning Datastrukturer (DAT036)

Innehåll. Föreläsning 12. Binärt sökträd. Binära sökträd. Flervägs sökträd. Balanserade binära sökträd. Sökträd Sökning. Sökning och Sökträd

Tommy Färnqvist, IDA, Linköpings universitet

Föreläsning 6. Sökträd: AVL-träd, Multi-Way -sökträd, B-träd TDDC70/91: DALG. Innehåll. Innehåll. 1 AVL-träd

Föreläsning 13 Datastrukturer (DAT037)

Tommy Färnqvist, IDA, Linköpings universitet

Föreläsning Datastrukturer (DAT037)

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 8 Erik Nilsson, Institutionen för Datavetenskap, LiU

TDDI16 Datastrukturer och algoritmer Övningsuppgifter hösten 2014

Hitta k största bland n element. Föreläsning 13 Innehåll. Histogramproblemet

Teoretisk del. Facit Tentamen TDDC (6)

TDDC70/TDDC91 Datastrukturer och algoritmer Övningsuppgifter hösten 2013

Datastrukturer. föreläsning 10. Maps 1

Facit Tentamen TDDC kl (6)

Teoretisk del. Facit Tentamen TDDC kl (6) 1. (6p) "Snabba frågor" Alla svar motiveras väl.

Föreläsning 8 Datastrukturer (DAT037)

Linjär sökning. Föreläsning 12. Binär sökning. Exempel: Binära sökträd. Binärt sökträd

Föreläsning 13 Datastrukturer (DAT037)

Föreläsning 7 Datastrukturer (DAT037)

Programkonstruktion och. Datastrukturer

Tentamen Datastrukturer (DAT037)

Programmering för Språkteknologer II. Innehåll. Associativa datastrukturer. Associativa datastrukturer. Binär sökning.

Föreläsning 9 Innehåll

Datastrukturer och algoritmer. Föreläsning 15 Inför tentamen

Föreläsning 2 Datastrukturer (DAT037)

Tildatenta Lösningsskiss

Fredag 10 juni 2016 kl 8 12

Tommy Färnqvist, IDA, Linköpings universitet. 1 Prioritetsköer Heapar Tillämpning... 3

Programkonstruktion och Datastrukturer

Föreläsning Datastrukturer (DAT037)

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 5 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Teoretisk del. Facit Tentamen TDDC kl (6) 1. (6p) "Snabba frågor" Alla svar motiveras väl.

Datastrukturer i kursen. Föreläsning 8 Innehåll. Träd rekursiv definition. Träd

Tommy Färnqvist, IDA, Linköpings universitet. 2 Rekursion i C Implementation av rekursion Svansrekursion En till övning...

Tommy Färnqvist, IDA, Linköpings universitet

Sortering. Brute-force. Sortering Ordna element enligt relation mellan nyckelvärden

Inlämningsuppgiften. Föreläsning 9 Innehåll. Träd. Datastrukturer i kursen

Föreläsning Datastrukturer (DAT036)

Föreläsning Datastrukturer (DAT036)

13 Prioritetsköer, heapar

Lösningsförslag till tentamen Datastrukturer, DAT037 (DAT036), Tiden det tar att utföra en iteration av loopen är oberoende av värdet på

Översikt. Stegvis förfining. Stegvis förfining. Dekomposition. Algoritmer. Metod för att skapa ett program från ett analyserat problem

Introduktion till algoritmer - Lektion 4 Matematikgymnasiet, Läsåret Lektion 4

Tentamen kl Uppgift 4. Uppgift 5

Föreläsning 1 Datastrukturer (DAT037)

Datastrukturer. föreläsning 9. Maps 1

Datastrukturer och algoritmer

Linjärt minne. Sammanhängande minne är ej flexibelt. Effektivt

Föreläsning 2. Stackar, köer och listor TDDC91,TDDE22,725G97: DALG. Innehåll. 1 ADT stack. 1.1 Tillämpningar

Datastrukturer. föreläsning 3. Stacks 1

Algoritmer och datastrukturer TDA143

Tentamen Datastrukturer (DAT036)

Grundläggande logik och modellteori

Sökning. Översikt. Binärt sökträd. Linjär sökning. Binär sökning. Sorterad array. Linjär sökning. Binär sökning Hashtabeller

Föreläsning 12 Innehåll

Föreläsning 11 Innehåll. Sortering. Sortering i Java. Sortering i Java Comparable. Sortering. O(n 2 )-algoritmer: urvalssortering insättningssortering

Transkript:

Föreläsning 9 Heap-sort, merge-sort. Undre gränser för sortering. Sortering i linjär tid? TDDC70/91: DALG Utskriftsversion av föreläsning i Datastrukturer och algoritmer 4 oktober 2013 Tommy Färnqvist, IDA, Linköpings universitet 9.1 Innehåll Innehåll 1 Sortering 1 1.1 Heap-sort........................................... 1 1.2 Merge-sort........................................... 1.3 Sammanfattning........................................ 10 2 En undre gräns för jämförelsebaserad sortering 11 3 Sortering i linjär tid? 14 3.1 Counting-sort......................................... 14 3.2 Bucket-sort.......................................... 22 3.3 Radix-sort........................................... 23 4 Hålkortsteknologi 2 9.2 1 Sortering 1.1 Heap-sort Sortering med prioritetskö Använd en prioritetskö för att sortera en samling jämförbara element Sätt in elementen med en serie insättningsoperationer Ta bort elementen i sorterad ordning med en serie removemin-operationer Körtiden beror på implementationen av prioritetskön: Osorterad sekvens ger urvalssortering och O(n 2 ) tid Sorterad sekvens ger insättningssortering och O(n 2 ) tid Kan vi åstadkomma något bättre? procedure PQSORT(S) P tom priokö while S.ISEMPTY() do e S.REMOVE(S.FIRST()) P.INSERT(e) while P.ISEMPTY() do e P.REMOVEMIN() S.INSERTLAST(e) 1

9.3 Höjden av en heap Proposition 1 (8. i kursboken). En heap som lagrar n nycklar har höjd O(logn) Bevis. Vi använder att en heap är ett fullständigt binärt träd. Låt h vara höjden av en heap som lagrar n nycklar Eftersom det finns 2 i nycklar på djup i = 0,...h 1 och minst en nyckel på djup h får vi n 1 + 2 + 4 +... + 2 h 1 + 1 Alltså är n 2 h, d.v.s. h log 2 n djup 0 1 h 1 h nycklar 1 2 2 h 1 1 9.4 Insättning i en heap Metoden insert i ADT priokö svarar mot insättning av nyckel k i heapen Insättningsalgoritmen består av tre steg Hitta platsen för insättning z (det nya sista lövet) Lagra k vid z Återställ heapegenskapen 2 9 7 z nytt sista löv 2 z 9 7 1 9. Upheap Efter insättning av en ny nyckel k är det inte säkert att heapegenskapen fortfarande är uppfylld Metoden upheap återställer heapegenskapen genom att byta k längs uppåtgående stig från insättningsnoden upheap terminerar när nyckel k når roten eller en nod vars förälder har en nyckel som inte är större än k Eftersom en heap har höjd O(logn) går upheap i tid O(logn) 2 1 z 9 7 1 z 9 7 2 9. 2

Borttagning från en heap Metoden removemin i ADT priokö svarar mot borttagning av rotnyckeln från heapen Borttagningsalgoritmen består av tre steg Ersätt rotnyckeln med nyckeln i det sista lövet w Ta bort w Återställ heapegenskapen 2 9 7 w sista lövet 7 9 w nytt sista löv 9.7 Downheap Efter ersättning av rotnyckeln med nyckel k från sista lövet är det inte säkert att heapegenskapen fortfarande är uppfylld Metoden downheap återställer heapegenskapen genom att byta k längs nedåtgående stig från insättningsnoden downheap terminerar när nyckel k når ett löv eller en nod vars barn har nycklar som inte är mindre än k Eftersom en heap har höjd O(logn) går downheap i tid O(logn) 7 9 w 9 7 w 9.8 Heap-sort Betrakta en priokö med n element implementerad m.h.a. en heap minnesåtgången är O(n) insert och removemin tar O(logn) tid size, isempty och min tar O(1) tid Genom att använda en heapbaserad priokö kan vi sortera en sekvens av n element i O(nlogn) tid Den resulterande algoritmen kallas heap-sort Heap-sort är mycket snabbare än kvadratiska sorteringsalgoritmer 9.9 3

Slå ihop två heapar Givet två heapar och en nyckel k Skapa en ny heap där rotnoden lagrar nyckel k och med de två givna heaparna som delträd Kör downheap för att återställa heapegenskapen 3 2 8 4 7 3 2 8 4 2 3 4 8 7 9.10 : Konstruktion av heap botten-upp 10 7 8 2 11 27 1 1 4 12 7 23 20 1 1 4 12 7 23 20 2 11 27 1 1 4 12 7 23 20 9.11 : Konstruktion av heap botten-upp 2 11 27 1 1 4 12 9 23 20 1 4 20 1 2 12 11 9 23 27 9.12 4

: Konstruktion av heap botten-upp 7 8 1 4 20 1 2 12 11 9 23 27 4 1 8 20 1 2 7 12 11 9 23 27 9.13 : Konstruktion av heap botten-upp 10 4 1 8 20 1 2 7 12 11 9 23 27 4 1 7 8 20 1 2 10 12 11 9 23 27 9.14 Analys Vi visualiserar värstafallstiden för ett anrop till downheap med en stig som först går till höger och sedan upprepade gånger går till vänster till botten av heapen Eftersom varje nod traverseras av som mest två sådana stigar är det totala antalet stigar O(n) Alltså är tiden för att konstruera en heap botten-upp O(n) Den här konstruktionsmetoden är snabbare än n upprepade insättningar och gör att första fasen av heap-sort blir effektivare 9.1 1.2 Merge-sort Söndra-och-härska Merge-sort är en sorteringsalgoritm baserad på söndra-och-härska Likt heap-sort

har den exekveringstid O(nlogn) Olikt heap-sort använder den inte en priokö till hjälp accessar den data på ett sekvensiellt sätt (lämpligt för att sortera data på disk) 9.1 Merge-sort Merge-sort på en indatasekvens S med n element består av tre steg: Söndra: dela S i två sekvenser S 1 och S 2 med vardera ca n/2 element Härska: sortera S 1 och S 2 rekursivt Kombinera: slå ihop (merge) S 1 och S 2 till en unik sorterad sekvens procedure MERGESORT(S) if S.SIZE() > 1 then (S 1,S 2 ) PARTITION(S.SIZE()/2) MERGESORT(S 1 ) MERGESORT(S 2 ) S MERGE(S 1,S 2 ) 9.17 Slå ihop två sorterade sekvenser Kombineringssteget: slå ihop två sekvenser A och B till en sorterad sekvens S innehållande unionen av elementen i A och B Att slå ihop två sorterade sekvenser, var och en med n/2 element implementerade med dubbellänkade listor, tar O(n) tid function MERGE(A, B) S tom sekvens while A.ISEMPTY() B.ISEMPTY() do if A.FIRST.ELEMENT() < B.FIRST.ELEMENT() then S.INSERTLAST(A.REMOVE(A.FIRST())) else S.INSERTLAST(B.REMOVE(B.FIRST())) while A.ISEMPTY() do S.INSERTLAST(A.REMOVE(A.FIRST())) while B.ISEMPTY() do S.INSERTLAST(B.REMOVE(B.FIRST())) return S 9.18 Merge-sortträdet Exekveringen av merge-sort kan visualiseras som ett binärt träd Varje nod representerar ett rekursivt anrop till merge-sort och lagrar Osorterad sekvens före exekveringen och dess partition Sorterad sekvens efter exekveringen Roten är ursprungsanropet Löven är anrop på delsekvenser av storlek 0 eller 1 7 2 9 4 2 4 7 9 7 2 2 7 9 4 4 9 7 7 2 2 9 9 4 4 9.19

: Exekvering av merge-sort Partitionera 7 2 9 4 3 8 1 7 8 9 7 2 9 4 2 4 7 9 3 8 1 1 3 8 7 2 2 9 4 4 9 3 8 3 1 1 7 2 9 4 3 8 1 9.20 : Exekvering av merge-sort Rekursivt anrop, partitionera 7 2 9 4 3 8 1 7 8 9 7 2 9 4 2 4 7 3 8 1 8 7 2 2 9 4 4 9 3 8 3 1 1 7 2 9 4 3 8 1 9.21 : Exekvering av merge-sort Rekursivt anrop, partitionera 7 2 9 4 3 8 1 7 8 9 7 2 9 4 2 4 7 3 8 1 1 3 8 7 2 2 7 9 4 9 4 3 8 3 8 1 1 7 2 9 4 3 8 1 9.22 7

: Exekvering av merge-sort Rekursivt anrop, basfall 7 2 9 4 3 8 1 7 8 7 2 9 4 2 4 7 3 8 1 7 2 2 9 4 4 9 3 8 3 1 1 7 7 2 2 9 9 4 4 3 3 8 8 1 1 9.23 : Exekvering av merge-sort Rekursivt anrop, basfall 7 2 9 4 3 8 1 7 8 7 2 9 4 2 4 7 3 8 1 1 3 7 2 2 7 9 4 4 9 3 8 3 8 1 1 7 7 2 2 9 9 4 4 3 3 8 8 1 1 9.24 : Exekvering av merge-sort Slå ihop 7 2 9 4 3 8 1 7 8 7 2 9 4 2 4 7 3 8 1 1 3 8 7 2 2 7 9 4 4 9 3 8 3 8 1 1 7 7 2 2 9 9 4 4 3 3 8 8 1 1 9.2 8

: Exekvering av merge-sort Rekursivt anrop,..., basfall 7 2 9 4 3 8 1 7 8 7 2 9 4 2 4 7 3 8 1 1 3 8 7 2 2 7 9 4 4 9 3 8 3 8 1 1 7 7 2 2 9 9 4 4 3 3 8 8 1 1 9.2 : Exekvering av merge-sort Slå ihop 7 2 9 4 3 8 1 7 8 9 7 2 9 4 2 4 7 9 3 8 1 1 3 8 7 2 2 7 9 4 4 9 3 8 3 8 1 1 7 7 2 2 9 9 4 4 3 3 8 8 1 1 9.27 : Exekvering av merge-sort Rekursivt anrop,..., slå ihop, slå ihop 7 2 9 4 3 8 1 7 8 9 7 2 9 4 2 4 7 9 3 8 1 1 3 8 7 2 2 7 9 4 4 9 3 8 3 8 1 1 7 7 2 2 9 9 4 4 3 3 8 8 1 1 9.28 9

: Exekvering av merge-sort Slå ihop 7 2 9 4 3 8 1 7 8 9 7 2 9 4 2 4 7 9 3 8 1 1 3 8 7 2 2 7 9 4 4 9 3 8 3 8 1 1 7 7 2 2 9 9 4 4 3 3 8 8 1 1 9.29 Analys av merge-sort Höjden h av merge-sortträdet är O(logn) vid varje rekursivt anrop delar vi sekvensen på mitten Det totala arbetet som utförs i noderna på djup i är O(n) vi partitionerar och slår ihop 2 i sekvenser av storlek n/2 i vi gör 2 i+1 rekursiva anrop Alltså är den totala exekveringstiden för merge-sort O(nlogn) 9.30 Analys av merge-sort djup #sekv strl 0 1 n 1 2 n/2 i 2 i n/2 i 9.31 1.3 Sammanfattning Sammanfattning så långt 10

Algoritm selection-sort insertion-sort quick-sort heap-sort merge-sort Tid O(n 2 ) O(n 2 ) O(n log n) förväntad O(n log n) O(n log n) Noteringar in-place långsam (bra för små indata) in-place långsam (bra för små indata) in-place, randomiserad snabbast (bra för stora indata) in-place snabb (bra för stora indata) sekvensiell dataaccess snabb (bra för enorma indata) 9.32 2 En undre gräns för jämförelsebaserad sortering Jämförelsebaserad sortering Många sorteringsalgoritmer är jämförelsebaserade De sorterar genom att göra jämförelser mellan par av objekt : insertion-sort, selection-sort, heap-sort, merge-sort, quick-sort,... Låt oss därför försöka härleda en undre gräns för exekveringstiden i värsta fall för varje algoritm som använder jämförelse för att sortera n element x 1,x 2,...,x n Är x i < x j? nej ja 9.33 Räkna jämförelser Låt oss enbart räkna jämförelser Varje möjlig körning av en algoritm motsvaras av en rot-till-lövstig i ett beslutsträd x i < x j? x a < x b? x c < x d? x e < x f? x k < x l? x m < x o? x p < x q? 11

9.34 : Beslutsträd Sort x 1, x 2,, x n 1:2 2:3 1:3 123 1:3 213 2:3 132 312 231 321 Varje intern nod är märkt i : j för i, j {1,2,...,n} Vänster delträd visar efterföljande jämförelser om x i x j Höger delträd visar efterföljande jämförelser om x i x j 9.3 : Beslutsträd Sort x 1, x 2, x 3 = 9, 4, : 2:3 1:2 9 4 1:3 123 1:3 213 2:3 132 312 231 321 Varje intern nod är märkt i : j för i, j {1,2,...,n} Vänster delträd visar efterföljande jämförelser om x i x j Höger delträd visar efterföljande jämförelser om x i x j 9.3 : Beslutsträd Sort x 1, x 2, x 3 = 9, 4, : 2:3 1:2 1:3 9 123 1:3 213 2:3 132 312 231 321 Varje intern nod är märkt i : j för i, j {1,2,...,n} Vänster delträd visar efterföljande jämförelser om x i x j Höger delträd visar efterföljande jämförelser om x i x j 9.37 12

: Beslutsträd Sort x 1, x 2, x 3 = 9, 4, : 2:3 1:2 1:3 123 1:3 132 312 213 4 2:3 231 321 Varje intern nod är märkt i : j för i, j {1,2,...,n} Vänster delträd visar efterföljande jämförelser om x i x j Höger delträd visar efterföljande jämförelser om x i x j 9.38 : Beslutsträd Sort x 1, x 2, x 3 = 9, 4, : 2:3 1:2 1:3 123 1:3 213 2:3 132 312 231 321 4 9 Varje löv innehåller en permutation π(i),π(2),...,π(n) för att indikera att ordningen x π(1) x π(2)... x π(n) har etablerats 9.39 Beslutsträdsmodellen Ett beslutsträd kan modellera exekveringen av vilken jämförelsebaserad sorteringsalgoritm som helst: Ett träd för varje storlek på indata Betrakta algoritmen som att exekveringen delas närhelst två element jämförs Trädet innehåller alla jämförelser längs alla tänkbara följder av instruktioner Körtiden för algoritmen = längden av stigen som traverseras Körtiden i värsta fall = höjden av trädet 9.40 Beslutsträdets höjd Höjden av beslutsträdet är en undre gräns för exekveringstiden i värsta fallet Varje tänkbar permutation av indata måste leda till ett separat utdatalöv Om det inte vore så skulle något indata...4... ha samma utdataordning som...4... vilket skulle vara fel Eftersom det finns n! = 1 2... n löv är höjden av trädet minst log(n!) 9.41 Den undre gränsen Varje jämförelsebaserad sorteringsalgoritm använder minst log(n!) tid i värsta fallet Därför använder en sådan algoritm minst tid ( n ) n 2 log(n!) log = (n/2) log(n/2) 2 Alltså är exekveringstiden för alla jämförelsebaserade sorteringsalgoritmer Ω(nlogn) i värsta fallet 9.42 13

3 Sortering i linjär tid? Några fall då man kan sortera snabbare än nlogn Bara ett konstant antal olika element ska sorteras Θ(n) med räknesortering Elementen som ska sorteras är tal som är jämnt fördelade i ett visst intervall Θ(n) med bucket-sort Elementen som ska sorteras är strängar som består av d siffror (S[i] = s i,1 s i,2...s i,d ) Θ(nd) med radix-sort Om d är konstant får vi linjär tidskomplexitet Om vi räknar antalet siffror i indata får vi linjär tidskomplexitet Θ(N), där N = nd 9.43 3.1 Counting-sort Räknesortering Require: A[1,...,n], där A[ j] {1,2,...,k} function COUNTINGSORT(A) Hjälparray för räkning: C[1,..., k] Hjälparray för lagring av resultatet: Res[1,...,n] for i 1 to k do C[i] 0 for j 1 to n do C[A[ j]] C[A[ j]] + 1 for i 2 to k do C[i] C[i] +C[i 1] for j n downto i do Res[C[A[ j]]] A[ j] C[A[ j]] C[A[ j]] 1 C[i] = {nyckel = i} C[i] = {nyckel i} return Res 9.44 Counting-sort C: Res: 9.4 14

Loop 1 C: 0 0 0 0 Res: for i 1 to k do C[i] 0 9.4 Loop 2 C: 0 0 0 1 Res: for j 1 to n do C[A[ j]] C[A[ j]] + 1 C[i] = {nyckel = i} 9.47 1

Loop 2 C: 1 0 0 1 Res: for j 1 to n do C[A[ j]] C[A[ j]] + 1 C[i] = {nyckel = i} 9.48 Loop 2 C: 1 0 1 1 Res: for j 1 to n do C[A[ j]] C[A[ j]] + 1 C[i] = {nyckel = i} 9.49 1

Loop 2 C: 1 0 1 2 Res: for j 1 to n do C[A[ j]] C[A[ j]] + 1 C[i] = {nyckel = i} 9.0 Loop 2 C: 1 0 2 2 Res: for j 1 to n do C[A[ j]] C[A[ j]] + 1 C[i] = {nyckel = i} 9.1 17

Loop 3 C: 1 0 2 2 Res: C': 1 1 2 2 for i 2 to k do C[i] C[i] + C[i 1] C[i] = {nyckel i} 9.2 Loop 3 C: 1 0 2 2 Res: C': 1 1 3 2 for i 2 to k do C[i] C[i] + C[i 1] C[i] = {nyckel i} 9.3 18

Loop 3 C: 1 0 2 2 Res: C': 1 1 3 for i 2 to k do C[i] C[i] + C[i 1] C[i] = {nyckel i} 9.4 Loop 4 C: 1 1 3 Res: 3 C': 1 1 2 for j n downto 1do Res[C[A[ j]]] A[ j] C[A[ j]] C[A[ j]] 1 9. 19

Loop 4 C: 1 1 2 Res: 3 4 C': 1 1 2 4 for j n downto 1do Res[C[A[ j]]] A[ j] C[A[ j]] C[A[ j]] 1 9. Loop 4 C: 1 1 2 4 Res: 3 3 4 C': 1 1 1 4 for j n downto 1do Res[C[A[ j]]] A[ j] C[A[ j]] C[A[ j]] 1 9.7 20

Loop 4 C: 1 1 1 4 Res: 1 3 3 4 C': 0 1 1 4 for j n downto 1do Res[C[A[ j]]] A[ j] C[A[ j]] C[A[ j]] 1 9.8 Loop 4 C: 0 1 1 4 Res: 1 3 3 4 4 C': 0 1 1 3 for j n downto 1do Res[C[A[ j]]] A[ j] C[A[ j]] C[A[ j]] 1 9.9 Analys 21

Θ(k) Θ(n) Θ(k) Θ(n) for i 1 to k do C[i] 0 for j 1 to n do C[A[ j]] C[A[ j]] + 1 for i 2 to k do C[i] C[i] + C[i 1] for j n downto 1 do Res[C[A[ j]]] A[ j] C[A[ j]] C[A[ j]] 1 Θ(n + k) 9.0 Exekveringstid Om k O(n) tar räknesortering Θ(n) tid Men sortering tar ju Ω(nlogn) tid! Vad är det som inte stämmer? Svar Jämförelsebaserad sortering tar Ω(nlogn) tid Counting-sort är inte jämförelsebaserad Faktum är att inte en enda jämförelse mellan några element utförs! 9.1 Stabil sortering Counting-sort är en stabil sorteringsmetod: den bevarar indataordningen mellan lika element Res: 1 3 3 4 4 Att fundera på: Vilka andra metoder för sortering är stabila? 9.2 3.2 Bucket-sort Bucket-sort Låt S vara en sekvens av n poster (nyckel, värde) med nycklar från [0,N 1] Bucket-sort använder nycklarna som index i en hjälparray B av sekvenser Analys: Fas 1: Töm sekvensen S genom att flytta varje post (k,v) sist i sin bucket B[k] Fas 2: För i = 0,...,N 1 flytta posterna i bucket B[i] till slutet av sekvensen S Fas 1 tar O(n) tid Fas 2 tar O(n + N) tid Bucket-sort tar O(n + N) tid procedure BUCKETSORT(S, N) B array med N tomma sekvenser 22

while S.ISEMPTY() do f S.FIRST() (k,o) S.REMOVE( f ) B[k].INSERTLAST((k, o)) for i 0 to N 1 do while B[i].ISEMPTY() do f B[i].FIRST() (k,o) B[i].REMOVE( f ) S.INSERTLAST((k, o)) 9.3 : Nycklar från [0, 9] 7, d 1, c 3, a 7, g 3, b 7, e Fas 1 1, c 3, a 3, b 7, d 7, g 7, e B 0 7 8 9 Fas 2 1, c 3, a 3, b 7, d 7, g 7, e 9.4 Egenskaper och utökningar Nycklarnas typ Nycklarna används som index i en array och kan inte vara objekt av godtycklig typ Stabil sortering Den relativa ordningen av alla par av data med samma nycklar är bevarad efter exekveringen av algoritmen Utökningar Heltalsnycklar från [a,b] Sätt in (k,v) i bucket B[k a] Strängnycklar från en ändlig mängd strängar D Sortera D och beräkna rangen r(k) för varje sträng k D i den sorterade sekvensen Sätt in (k,v) i bucket B[r(k)] 9. 3.3 Radix-sort Radix-sort Ursprung: Herman Holleriths kortsorteringsmaskin för folkräkningen 1890 i USA Siffra-för-siffrasortering Holleriths (dåliga) ursprungsidé: sortera på mest signifikant siffra först Bra idé: sortera på minst signifikant siffra först med en extern stabil sorteringsrutin 9. 23

Modernt hålkort från IBM Producerat av WWW Virtual Punchcard Server Så det är därför skalfönster har 80 kolumner! 9.7 : Exekvering av radix-sort 3 2 9 4 7 7 8 3 9 4 3 7 2 0 3 7 2 0 3 4 3 4 7 7 3 2 9 8 3 9 7 2 0 3 2 9 4 3 8 3 9 3 4 7 7 3 2 9 3 4 3 4 7 7 7 2 0 8 3 9 9.8 Korrekthet för radix-sort Använd induktion över sifferposition Antag att talen är sorterade på sina t 1 lägsta siffror Sortera på siffra t 7 2 0 3 2 9 4 3 8 3 9 3 4 7 7 3 2 9 3 4 3 4 7 7 7 2 0 8 3 9 9.9 24

Korrekthet för radix-sort Använd induktion över sifferposition Antag att talen är sorterade på sina t 1 lägsta siffror Sortera på siffra t 7 2 0 3 2 9 4 3 8 3 9 3 4 7 7 Två tal som skiljer sig i siffra t blir korrekt sorterade 3 2 9 3 4 3 4 7 7 7 2 0 8 3 9 9.70 Korrekthet för radix-sort Använd induktion över sifferposition Antag att talen är sorterade på sina t 1 lägsta siffror Sortera på siffra t 7 2 0 3 2 9 4 3 8 3 9 3 4 7 7 Två tal som skiljer sig i siffra t blir korrekt sorterade Två tal som är lika i siffra t får samma ordning som i indata rätt ordning 3 2 9 3 4 3 4 7 7 7 2 0 8 3 9 9.71 Analys av radix-sort Antag att counting-sort används som extern sorteringsrutin Sortera n maskinord om b bitar vardera Vi kan se det som att varje ord har b/r siffror i bas 2 r : 8 8 8 8 32-bitars ord r = 8 b/r = 4 pass av counting-sort på siffror i bas 2 8 eller r = 1 b/r = 2 pass av counting-sort på siffror i bas 2 1 Hur många pass bör vi göra? 9.72 2

Analys av radix-sort Kom ihåg: counting-sort tar tid Θ(n + k) för att sortera n tal från [0,k 1]. Om varje b-bitars ord bryts upp i r-bitars bitar tar varje pass av counting-sort Θ(n + 2 r ) tid. Eftersom det blir b/r pass får vi ( ) b T (n,b) = Θ r (n + 2r ) Välj r för att minimera T (n,b) Att öka r ger färre pass, men när r logn ökar tiden exponentiellt. 9.73 Att välja r ( ) b T (n,b) = Θ r (n + 2r ) Minimera T (n,b) genom att derivera och sätta till 0. Eller, observera att vi inte vill ha 2 r n och att det inte skadar asymptotiskt att välja r så stort som möjligt givet detta villkor. Valet r = logn medför T (n,b) = Θ(bn/logn). För tal i intervallet från 0 till n d 1 har vi b = d logn radix-sort kör i tid Θ(dn). 9.74 Slutsatser I praktiken är radix-sort snabb för stora indata, samt enkel att koda och underhålla. : 32-bitars tal Som mest 3 pass när man sorterar 2000 tal. Merge-sort och quick-sort använder minst log2000 = 11 pass. Nackdelar: Det går inte att sortera in-place med räknesortering. Det är också så att radix-sort inte har bra datalokalitet (vilket man kan se till att quick-sort har) vilket gör att en väl trimmad implementation av quick-sort kan vara snabbare på en modern processor med brant minneshierarki. 9.7 4 Hålkortsteknologi Herman Hollerith (180-1929) 1880 års folkräkning i USA tog nästan 10 år att bearbeta. Under tiden arbetade en föreläsare vid MIT fram hålkortsteknologin. Hans maskiner, inklusive en kortsorterare, gjorde att folkräkningen 1890 kunde slutföras på veckor. Han grundade The Tabulating Machine Company 1911, vilket gick samman med andra företag 1924 för att bilda International Business Machines 9.7 Hålkort Hålkort = datapost Hål = värde Algoritm = maskin + människa Replika av hålkort från folkräkningen 1900 [Howells 2000] 9.77 2

Holleriths tabuleringssytem Pantografisk hålmaskin Läsare manövrerad med handkraft Visare för räkneresultat Sorteringlåda Bild från [Howells 2000] 9.78 Ursprunget till radix-sort Holleriths patentansökan från 1899 talar om radix-sort med början från den mest signifikanta siffran: The most complicated combinations can readily be counted with comparatively few counters or relays by first assorting the cards according to the first items entering into the combinations, then reassorting each group according to the second item entering into the combination, and so on, and finally counting on a few counters the last item of the combination for each group of cards. Att köra radix-sort med minst signifikant siffra först verkar vara en uppfinning av maskinoperatörerna. 9.79 Sorteringsmaskinen En operatör sätter in ett kort i pressen. Stift på pressen når genom hålen i hålkortet och får kontakt med kvicksilverfyllda bägare under kortet. När ett visst siffervärde slås in lyfts locket på motsvarande sorteringsfack. Operatören lägger kortet i facket Holleriths Tabulator, Pantograph, Press och Sorter och stänger locket. När alla kort bearbetats öppnas frontpanelen och korten samlas in i ordning, vilket ger ett pass av en stabil sorteringsrutin. 9.80 27