Algorithms and Architectures I Rasmus Løvenstein Olsen (RLO), Jimmy Jessen Nielsen (JJE) Mm: A little bit more about sorting - and more times for exercises - November 4, 2008 1
Algorithms and Architectures II 1. Introduction to analysis and design of algorithms(rlo) 2. Recursive algorithms and recurrences (RLO). More about recurrences (RLO) 4. Greedy algorithms, backtracking and more recurrences(rlo). ounting, probabilities and randomized algorithms (RLO). More sorting algorithms: Heap sort and quick sort (RLO). A little bit more about sorting - and more times for exercises (RLO) 8. Hash tables, Hashing and binary search trees (RLO) 9. Binary search trees, red-black trees (JJE) 10. Red-black trees continued + string matching (JJE) 2
Dagsorden Sorteringsalgoritmer i (u)lineær tid Eksempler på sorteringsalgoritmer i lineær tid ounting sort Radix sort Bucket sort Opsummering og konklusion Opgaver
Sortering i (u)linear tid. Tidligere har vi set på algoritmer der sorterer i O(n 2 ) eller O(nLog(n)) tid Kan vi gøre det hurtigere? Jo, i lineær tid, dvs. T(n) = O(n) Hvad er problemet med tidligere sorteringsalgoritmer? Vi benytter os af sammenligninger, såsom a 1 =a 2, a 1 >a 2, a 1 <a 2, og opnår et beslutningstræ som f.eks. 1:2 > 2: 1: > {1,2,} 1: {2,1,} > 1: > {1,,2} {,1,2} {2,,1} {,2,1} Med eksemplet opnår vi! = mulige slutpunkter 4
Sortering i (u)linear tid. #2 Udførslen af en sorteringsalgoritme baseret på sammenligning er det samme som en sti gennem sådan et træ Ved hvert blad udføres sammenligningen a i > a j, a i a j Det giver os et sæt af mulige terminerende muligheder Helt præcist med n elementer bliver det n! Længden fra toppen til bunden af et beslutningstræ angiver den værste situation for en sorteringsalgoritme Fordi den i hver gren skal udføre en sammenligning En nedre grænse kan findes for kompleksiteten (tavle) Følgende er at heap-sort og merge-sort er asymptotisk optimale sorteringsalgoritmer
Dagsorden Sorteringsalgoritmer i (u)lineær tid Eksempler på sorteringsalgoritmer i lineær tid ounting sort Radix sort Bucket sort Opsummering og konklusion Opgaver
ounting sort Hvad nu hvis vi ikke benytter os af sammenligninger? Hmmmmm hvordan det? Vi baserer sorteringen på frekvensen (hyppigheden) af tal Vi antager her at vi arbejder med numeriske heltals værdier ounting sort A[1..n] : Input array B[1..n] : Output array. Vi flytter A over i B (sorteret selfølgelig)! [0..k] : Midlertidigt array vi benytter til at holde styr på forekomsten af elementer i A Note: så selvom vi kan udføre sorteringen i lineær tid, koster det mere plads i hukommelsen end f.eks. Quicksort!
ounting sort #2 OUNTING-SORT (A, B, k) 1 For i = 0 to k For j = length(a) downto 1 2 do [i] = 0 8 do B[[A[j]]] = A[j] For j = 1 to length(a) 9 [A[j]] = [A[j]] - 1 4 do [A[j]] = [A[j]] +1 //Increment the counter For i = 1 to k do [i] = [i] + [i-1] //reate incremental index Bemærk: Linjerne - 4: Her tæller vi hyppigheden af elementer i arrayet A og lægger dem ind i Linjerne - : Her danner vi et inkrementerende indeks af hyppighederne Linjerne - 9: Her foretager vi sorteringen vha. indekseringen 8
Eksempel på eksekvering - optælling i linje - 4 1 2 4 8 1 2 4 8 A 2 0 2 0 A 2 0 2 0 0 1 2 4 0 1 2 4 0 0 0 0 0 0 1 0 2 1 0 1 0 0 1 0 0 0 1 0 2 2 0 1 0 0 1 0 0 1 2 0 2 2 0 1 0 0 1 1 0 1 2 0 2 0 1 1 0 1 1 0 1 Samlet tid: T(n) = Θ(k) 9
Dannelse af indeks 0 1 2 4 0 1 2 4 2 0 2 0 1 2 2 4 8 Generering af en akkumuleret sum danner vores indeks Samlet tid for generering af indeks: T(n) = Θ(k) Nu kan vi så begynde at sortere ved flytning af A ind i B vha. B[[A[j]]] = A[j] i linje 8 1 2 4 8 A B 2 0 2 0 - - - - - - - - 0 1 2 4 2 2 4 8 10
Og fortsættelse af indsættelse i B B[[A[j]]] = A[j] i linje 8 1 2 4 8 A 2 0 2 0 B - 0- - - - - - 0 1 2 4 1 2 4 8 12 2 4 8 A 2 0 2 0 B - 0 - - - - - 0 1 2 4 1 2 4 8 11
Og fortsættelse af indsættelse i B B[[A[j]]] = A[j] i linje 8 1 2 4 8 A 2 0 2 0 B - 0-2- - - 0 1 2 4 1 2 4 8 1 2 4 8 A 2 0 2 0 B 0-0 - 2 - - 0 1 2 4 01 2 8 12
Og fortsættelse af indsættelse i B B[[A[j]]] = A[j] i linje 8 1 2 4 8 A 2 0 2 0 B 0 0-2 - - 0 1 2 4 1 2 4 8 0 2 4 8 A 2 0 2 0 B 0 0-2 - 0 1 2 4 0 2 4 8 1
Og fortsættelse af indsættelse i B B[[A[j]]] = A[j] i linje 8 1 2 4 8 A B 2 0 2 0 0 0 2-2 0 1 2 4 0 2 2 4 Samlet tid: T(n) = Θ(n) 14
Egenskaber for counting sort Samlet tid for udførsel af counting sort T(n, k) = Θ(n+k) I praksis har vi at k = O(n), medførende at T(n) = Θ(n) ounting sort har derudover et meget vigtigt egenskab Den er stabil: tal der har samme værdi optræder i samme rækkefølge i output arrayet, som de gjorde i input arrayet Det egenskab kan vi udnytte til en mere avanceret form for sortering 1
Dagsorden Sorteringsalgoritmer i (u)lineær tid Eksempler på sorteringsalgoritmer i lineær tid ounting sort Radix sort Bucket sort Opsummering og konklusion Opgaver 1
Radix sort - lidt trivia Men først lidt moderne teknologi (ok, så den var moderne i 192) IBMs 80 serie kunne sortere punch cards Type 80: 40 cpm (192) Type 84: 2000 cpm (>190) IBM s serie 80 sorterings maskine fra 192 FORTRAN udtryk på punch card form: Z = Y + W IBM s port-a-punch fra 198 1
18 Ideen bag radix sort Radix sort baserer sig på at sortere tal ved Først at sortere dem efter mindste ciffer først (enere) Dernæst næst mindste ciffer (tiere) osv. op til det højeste ciffer (hundrede) 9 8 9 8 0 2 4 9 2 0 2 4 4 9 8 4 9 8 4 4 4 9 2 9 0 2 2 0 2 9 2 4 1 2 4
Radix sort Koden for radix sort er simpel RADIX-SORT (A, d) 1 For i = 1 to d 2 do Use Stable Sort to sort Array A on digit i Hvis den stabile anvendte sorteringsalgoritme sorterer på Θ(n+k) tid, så sorterer radix sort på Θ(d(n+k)) Hvis d er konstant og k = O(n) sorterer radix i lineær tid! Givet n b-bit numre og for ethvert positiv heltal r b, sorterer radix-sort korrekt på Θ((b/r)(n+2 r )) tid 19
Dagsorden Sorteringsalgoritmer i (u)lineær tid Eksempler på sorteringsalgoritmer i lineær tid ounting sort Radix sort Bucket sort Opsummering og konklusion Opgaver 20
Bucket sort Baserer sig på et koncept om at inddele data i passende buckets og sortere de enkelte buckets Efter sortering i de enkelte buckets grupperes resultaterne i et dermed sorteret array OUNTING-SORT (A) 1 n = length(a) 2 For i = 1 to n do insert A[i] into list B[[nA[i]] 4 For i = 0 to n -1 do sort list B[i] with insertion-sort oncatenate lists B[0], B[1],, B[n-1] in order 21
Bucket sort - eksempel A B 1 0.8 0 / 1 0.12 2 0.1 1 0.12 0.1 / 2 0.1 4 8 9 10 0.9 0.2 0.2 0.94 0.21 0.12 0.2 0.8 2 4 8 9 / / / 0.21 0.9 / 0.8 / 0.2 0.94 / 0.2 0.2 / 0.8 / 4 8 9 10 0.21 0.2 0.2 0.9 0.8 0.2 0.8 0.94 22
Bucket sort - tidskompleksitet Antager at input er tal genereret af en stokastisk process, der distribuerer data uniformt i intervallet [0, 1) Samtlige kode linjer tager O(n) tid, med undtagelsen af kaldet til Insertion-Sort der som sagt tager O(n 2 ) tid Men hvordan kan vi sige en algoritme kører i lineær tid, O(n), når selve sorteringen sker i kvadratisk tid, O(n 2 )? Tavle gennemgang Og dermed kan vi sige at bucket sort kører i forventet lineær tid, Θ(n) 2
Dagsorden Sorteringsalgoritmer i (u)lineær tid Eksempler på sorteringsalgoritmer i lineær tid ounting sort Radix sort Bucket sort Opsummering og konklusion Opgaver 24
Opsummering og konklusion Vi så at sammenlignings baserede sorterings algoritmer kører højest i ulineær tid, O(nLog(n)), eller endnu værre O(n 2 ) Vi kan komme ned på lineær tid O(n) ved andre metoder, men baseret på At data er numerisk At vi kender og udnytter egenskaber omkring data, f.eks. Heltal kan tælles, floats kan vi putte i spande osv. Selvom vi kan få sortering til at foregå i lineær tid, er det ikke givet at det er den bedste løsning. Vi skal f.eks. også tage i betragtning at vi har brug for ekstra plads til nogle af algoritmerne!! 2
Dagsorden Sorteringsalgoritmer i (u)lineær tid Eksempler på sorteringsalgoritmer i lineær tid ounting sort Radix sort Bucket sort Opsummering og konklusion Opgaver 2
Opgaver Fortsæt med opgaver fra sidst 2