ID1020:Enkel Sortering Dr. Jim Dowling jdowling@kth.se kap 2.1 Slides adapted from Algorithms 4 th Edition, Sedgewick.
Ett sorteringsproblem T.ex. Student poster på ett universitet. Chen 3 A 991-878-4944 308 Blair Rohde 2 A 232-343-5555 343 Forbes Gazsi 4 B 766-093-9873 101 Brown post Furia 1 A 766-093-9873 101 Brown Kanaga 3 B 898-122-9643 22 Brown Andrews 3 A 664-480-0023 097 Little nyckel Battle 4 C 874-088-1212 121 Whitman Sortering. Ordna om en array (följd) av N poster i stigande ordning. Andrews 3 A 664-480-0023 097 Little Battle 4 C 874-088-1212 121 Whitman Chen 3 A 991-878-4944 308 Blair Furia 1 A 766-093-9873 101 Brown Gazsi 4 B 766-093-9873 101 Brown Kanaga 3 B 898-122-9643 22 Brown Rohde 2 A 232-343-5555 343 Forbes 2
Sortering applikationer Library of Congress numbers FedEx packages contacts playing cards 3
Exempel: sortering klient (1) Mål. Sortera alla möjliga datatyper. T.ex.1. Sortera slumpmässiga reella tal i stigande ordning. ett exempel kommer senare public class Experiment { public static void main(string[] args) { int N = Integer.parseInt(args[0]); Double[] a = new Double[N]; for (int i = 0; i < N; i++) a[i] = StdRandom.uniform(); Insertion.sort(a); for (int i = 0; i < N; i++) StdOut.println(a[i]); % java Experiment 10 0.08614716385210452 0.09054270895414829 0.10708746304898642 0.21166190071646818 0.363292849257276 0.460954145685913 0.5340026311350087 0.7216129793703496 0.9003500354411443 0.9293994908845686 4
Exempel: sortering klient (2) Mål. Sortera alla möjliga datatyper. T.ex. 2. Sortera alla strängar i bokstavsordning. public class StringSorter { public static void main(string[] args) { String[] a = StdIn.readAllStrings(); Insertion.sort(a); for (int i = 0; i < a.length; i++) StdOut.println(a[i]); % more words3.txt bed bug dad yet zoo... all bad yes % java StringSorter < words3.txt all bad bed bug dad... yes yet zoo [suppressing newlines] 5
Exempel: sortering klient (3) Mål. Sortera alla möjliga datatyper. T.ex. 3. Sortera alla filer i en given mapp efter filnamn. % java FileSorter. import java.io.file; public class FileSorter { public static void main(string[] args) { File directory = new File(args[0]); File[] files = directory.listfiles(); Insertion.sort(files); for (int i = 0; i < files.length; i++) StdOut.println(files[i].getName()); Insertion.class Insertion.java InsertionX.class InsertionX.java Selection.class Selection.java Shell.class Shell.java ShellX.class ShellX.java 6
Totalordning Mål. Sortera alla möjliga datatyper (där sortering är väldefinierade). En totalordning är en binärrelation som satisfierar: - icke-symmetri: IF (v w och w v) THEN v = w. - transitiv: IF (v w och w x) THEN v x. - totalitet: antingen v w eller w v eller både. T.ex. - Vanlig ordningen för heltal och reella tal. - Kronologiska ordningen för datum och tider. - Bokstavsordning för strängar. Icke-transitive. Sten-sax-påse. 7
Callbacks (återanropsfunktion) Mål. Sortera alla möjliga datatyper (där sortering är väldefinierade). Hur kan sort() veta hur den ska jämföra data av olika typer, som Double, String, and java.io.file, utan att ha någon information om datatypen av postens nyckel? Callback = en referens till exekverbarkod. - Klienen skickar en array av objekt till sort() funktionen. - sort() funktionen anropar objekts compareto() metod vid behov. Att implementera callbacks. - Java: interfaces. - C: function pointers. - C++: class-type functors. - C#: delegates. - Python, Perl, ML, Javascript: first-class functions. 8
Callbacks i Java klient public class StringSorter { public static void main(string[] args) { String[] a = StdIn.readAllStrings(); Insertion.sort(a); for (int i = 0; i < a.length; i++) StdOut.println(a[i]); Comparable interface (inbyggd i Java) public interface Comparable<Item> { public int compareto(item that); inga beroenden på String datatypen datatyp implementation public class String implements Comparable<String> {... public int compareto(string b) {... return -1;... return +1;... return 0; sort implementation public static void sort(comparable[] a) { int N = a.length; for (int i = 0; i < N; i++) for (int j = i; j > 0; j--) if (a[j].compareto(a[j-1]) < 0) exch(a, j, j-1); else break; 9
Comparable API Implementera compareto() så att v.compareto(w): - definierar en totalordning; - returnerar en negativ heltal, noll, eller en positiv heltal IF v är respektiv mindre än, lika med, eller större än w. - kastar en exception om typer är inkompatibla typer (eller om en av dem är null). v w v w v w mindre än (returnera -1) lika med (returnera 0) större än (returnera +1) Inbyggda jämförbara typer. Integer, Double, String, Date, File,... Använder-definierade jämförbara typer. Implementera Comparable interface:n och instanser av klassen (objekt) kan jämföras med compareto metoden. 10
Implementera Comparable interface:n Date datatyp. Förenklad version av java.util.date. public class Date implements Comparable<Date>{ private final int month, day, year; public Date(int m, int d, int y) { month = m; day = d; year = y; jämför Date objekt bara med andra Date objekt public int compareto(date that) { if (this.year < that.year ) return -1; if (this.year > that.year ) return +1; if (this.month < that.month) return -1; if (this.month > that.month) return +1; if (this.day < that.day ) return -1; if (this.day > that.day ) return +1; return 0; 11
Enkel sortering (elementary sorting)
Selection sort (urvalssortering) algoritm demo Under iteration i, hitta index min av den minste resterande post. a[i] och a[min] byter plats. initial 14
Selection sort algoritm Algoritm. skannar från vänster till höger. Invarianter. - Poster till vänster av (inkluderande ) är sorterad i stigande ordning. - Ingen post till höger av är mindre än en post till vänster av. i slutordning 15
Två användbara sorterings hjälpfunktioner Hjälpfunktioner. Jämförelser och byte operationer på poster (objekt). Mindre än (less-than). Är posten (objekt) v mindre än w? private static boolean less(comparable v, Comparable w) { return v.compareto(w) < 0; Byte (exchange). Byt posten i array a[] vid index j med posten vid index k. private static void exch(comparable[] a, int j, int k) { Comparable swap = a[j]; a[j] = a[k]; a[k] = swap; 16
Selection sort innre slingan För att bevara algoritmen invarianter: - Flytta pekare till höger. i++; - Identifiera indexet av minsta posten till höger i array:n. i slutordning int min = i; for (int j = i+1; j < N; j++) { if (less(a[j], a[min])) { min = j; i slutordning - Byt indexet i med min, det minsta elementet. exch(a, i, min); i slutordning 17
Selection sort: Java implementation public class Selection { public static void sort(comparable[] a) { int N = a.length; for (int i = 0; i < N; i++) { int min = i; for (int j = i+1; j < N; j++) if (less(a[j], a[min])) min = j; exch(a, i, min); private static boolean less(comparable v, Comparable w) { /* as before */ private static void exch(comparable[] a, int i, int j) { /* as before */ 18
Selection sort: animeringar 20 poster i slumpordning algoritm position sorterade inte sorterade ännu http://www.sorting-algorithms.com/selection-sort 19
Selection sort: animeringar 20 delvis sorterade poster algoritm position sorterade inte sorterade ännu http://www.sorting-algorithms.com/selection-sort 20
Matematisk analys Vi använder följande kostnadsmodellen med de enkla sorteringsalgoritmerna: 1. antalet jämförelser (comparisons) 2. antalet byten (exchanges) Om algoritmen inte swappar element, då räknar vi antalet array accesser.
2 Selection sort: matematisk analys Sats. Selection sort jämför (N -1) + (N - 2) +... + 1 + 0 ~ N 2 / 2 gånger och byter N gånger. Körtiden är inte känslig mot indata. Kvadratisk tid, även om input är sorterad. Minimera kopieringen av data. Linjär antal byte.
Insertion Sort (Insättningssortering)
Insertion sort demo Under iteration i, a[i] byter plats med varje post som är större på vänstra sidan. 24
Insertion sort Algoritm. skannar från vänster till höger. Invarianter. - Poster till vänster om (inkluderande ) är i stigande ordning. - Poster till höger om har inte bearbetats än. sorterade inte bearbetat än 25
Insertion sort inner loop Bevara algoritm invarianterna: - Flytta pekare till höger. i++; sorterade inte sorterade ännu När pekare flyttar från höger till vänster, byt a[i] med varje post på vänstra sidan som är större. for (int j = i; j > 0; j--) if (less(a[j], a[j-1])) exch(a, j, j-1); else break; sorterade inte sorterade ännu 26
Insertion sort: Java implementation public class Insertion { public static void sort(comparable[] a) { int N = a.length; for (int i = 0; i < N; i++) { for (int j = i; j > 0; j--) { if (less(a[j], a[j-1])) { exch(a, j, j-1); else { break; private static boolean less(comparable v, Comparable w) { /* as before */ private static void exch(comparable[] a, int i, int j) { /* as before */ 27
Insertion sort: animering 40 poster i slumpordning algoritm position sorterade inte sorterade ännu http://www.sorting-algorithms.com/insertion-sort 28
Insertion sort: animering 40 omvänd-sorterade poster algoritm position sorterade inte sorterade ännu http://www.sorting-algorithms.com/insertion-sort 29
Insertion sort: animering 40 delvis sorterade poster algoritm position sorterade inte sorterade ännu http://www.sorting-algorithms.com/insertion-sort 30
Insertion sort: matematisk analys Sats. För att sortera en array i slumpordning med unika nycklar, insertion sort jämför ~ ¼ N 2 gånger och byter ~ ¼ N 2 gånger i genomsnitt. Bevis. Förväntat antal platser en post flyttar tillbaka är N/2 (halvvägs). 31
Insertion sort: trace 32
Insertion sort: analys Best case. Om array:n är i stigande ordning, insertion sort jämför N 1 gånger och byter 0 gånger. A E E L M O P R S T X Worst case. Om array:n är i nedstigande ordning (med unika element), insertion sort jämför ~ ½ N 2 gånger och byter ~ ½ N 2 gånger. X T S R P O M L F E A 33
Insertion sort: delvis sorterade arrayer Def. En inversion är ett par nycklar som är i fel ordningen. A E E L M O T R X P S T-R T-P T-S R-P X-P X-S (6 inversioner) Def. En array är delvis sorterade om antalet inversionerna är c N. - T.ex. 1. En sorterade array har 0 inversioner. - T.ex. 2. En subarray av längd 10 lagt till en sorteradea subarray av längd N. Sats. För delvis sorterade arrayer, insertion sort kör i linjärtid. Bevis. Antalet byten är lika med antalet inversionerna. antalet jämförelser = antalet byten + (N 1) 34
Insertion sort: förbättringar Binär insertion sort. Man kan använda binärsökning för att hitta den såkallade insertion point. - Antalet jämförelser ~ N lg N. - Men det är fortfarande kvadratisk i antalet array accesser. A C H H I M N N P Q X Y K B I N A R Y binärsök efter första nyckel > K 35
Shellsort
Shellsort översikt Kärnidén. Vi vill flytta poster mer än en position åt gången genom att exekvera h-sorting på array:n. Shellsort. [Shell 1959] h-sort array för nedstigande sekvens av värden av h. 37
h-sorting demo Vid iteration i, byt a[i] mot denna post som ligger h positioner till vänster om denna post är större än a[i]. 38
h-sorting Hur kör man h-sort på en array? Kör insertion sort, men med klivlängd (stride length) h. 3-sorting an array M O L E E X A S P R T E O L M E X A S P R T E E L M O X A S P R T E E L M O X A S P R T A E L E O X M S P R T A E L E O X M S P R T A E L E O P M S X R T A E L E O P M S X R T A E L E O P M S X R T Varför insertion sort? - Stora inkrement small subarray. - Små inkrement nästan sorterad. A E L E O P M S X R T 39
Shellsort exempel: inkrement av 7, 3, 1 input S O R T E X A M P L E 7-sort S O R T E X A M P L E M O R T E X A S P L E M O R T E X A S P L E M O L T E X A S P R E M O L E E X A S P R T 3-sort M O L E E X A S P R T E O L M E X A S P R T E E L M O X A S P R T E E L M O X A S P R T A E L E O X M S P R T A E L E O X M S P R T A E L E O P M S X R T A E L E O P M S X R T A E L E O P M S X R T 1-sort A E L E O P M S X R T A E L E O P M S X R T A E L E O P M S X R T A E E L O P M S X R T A E E L O P M S X R T A E E L O P M S X R T A E E L M O P S X R T A E E L M O P S X R T A E E L M O P S X R T A E E L M O P R S X T A E E L M O P R S T X resultat A E E L M O P R S T X 40
Shellsort: Java implementation public class Shell { public static void sort(comparable[] a) { int N = a.length; int h = 1; while (h < N/3) h = 3*h + 1; // 1, 4, 13, 40, 121, 364,... while (h >= 1) { // h-sort the array. for (int i = h; i < N; i++) { for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) exch(a, j, j-h); h = h/3; private static boolean less(comparable v, Comparable w) { /* as before */ private static void exch(comparable[] a, int i, int j) { /* as before */ 3x+1 inkrement sekvens insertion sort nästa inkrement 41
Shellsort: visualisering 42
Shellsort: animering 50 poster i slumpordning http://www.sorting-algorithms.com/shell-sort algoritm position h-sorted nuvarande subsekvens andra element 43
Shellsort: animering 50 delvis sorterade poster http://www.sorting-algorithms.com/shell-sort algoritm position h-sorted nuvarande subsekvens andra element 44
Shellsort: vilken inkrementsekvens ska man använda? Tvåpotens (powers of two). 1, 2, 4, 8, 16, 32,... Nej. Tvåpotens minus ett. 1, 3, 7, 15, 31, 63, Kanske. 3x + 1. 1, 4, 13, 40, 121, 364, OK. Lätt att beräkna. 45
Shellsort: intuition Sats. En h-sorted array förbli h-sorted efter ha kört g-sort på array:n. 7-sort S O R T E X A M P L E M O R T E X A S P L E M O R T E X A S P L E M O L T E X A S P R E M O L E E X A S P R T 3-sort M O L E E X A S P R T E O L M E X A S P R T E E L M O X A S P R T E E L M O X A S P R T A E L E O X M S P R T A E L E O X M S P R T A E L E O P M S X R T A E L E O P M S X R T A E L E O P M S X R T A E L E O P M S X R T still 7-sorted Utmaning. Bevisa detta faktum; det är svårare än vad man tror! 46
Shellsort: analys Sats. Tidskomplexitet av worst-case är antalet jämförelser i shellsort. När inkrementet är 3x+1, då är tidskomplexitet lika med N 3/2. Egenskap. Förväntade antalet jämförelser för att köra shellsort på en array i slumpordning med inkrementet lika med 3x+1 är. N compares 2.5 N ln N 0.25 N ln 2 N N 1.3 5,000 93K 106K 91K 64K 10,000 209K 230K 213K 158K 20,000 467K 495K 490K 390K 40,000 1022K 1059K 1122K 960K 80,000 2266K 2258K 2549K 2366K Anmärkning. En noggrann modell har inte hittats ännu (!) 47
Varför är shellsort intressant? En enkel idé kan leda till signifikant prestandsförbättringar. Användbart i praktiken. - Snabb om array:n inte är enorm. R, bzip2, /linux/kernel/groups.c - Mycket liten minneskomplexitet (använt i vissa inbyggda system). Enkel algoritm, icke-trivial prestanda, intressanta frågor. - Asymptotisk tidskomplexitet? - Bästa möjliga sekvens av inkrementet? - Average-case prestanda? uclibc öppet problem: hitta en bättre inkrement sekvens Läxa. Många bra algoritm har inte upptäckts ännu. 48
Enkel sortering sammanfattning algoritm best average worst selection sort N 2 N 2 N 2 insertion sort N N 2 N 2 Shellsort (3x+1) N log N? N 3/2 Mål N N log N N log N Tidskomplexitet av körtiden för att sortera en array av N poster 49
Blandning (Shuffling)
Hur blandar man en array? Mål. Ordna om en array så att resultatet är en slumpmässig valda permutation. alla permutationer har samma sannolikhet 51
Hur blandar man en array? Mål. Ordna om en array så att resultatet är en slumpmässig valda permutation. alla permutationer har samma sannolikhet 52
Shuffle sort Generera ett slumpmässigt reellt tal för varje element i array:n. Sortera array:n. användbart för att blanda spaltar i en kalkylblad 0.8003 0.9706 0.9157 0.9649 0.1576 0.4854 0.1419 0.4218 0.9572 53
Shuffle sort Generera ett slumpmässigt reellt tal för varje element i array:n. Sortera array:n. användbart för att blanda spaltar i en kalkylblad 0.1419 0.1576 0.4218 0.4854 0.8003 0.9157 0.9572 0.9649 0.9706 54
Shuffle sort - Generera ett slumpmässigt reellt tal för varje element i array:n. - Sortera array:n. användbart för att blanda spaltar i en kalkylblad 0.1419 0.1576 0.4218 0.4854 0.8003 0.9157 0.9572 0.9649 0.9706 Sats. Shuffle sort resulterar i en slumpmässig valda permutation (uniformly random permutation). Vi antar reella tal valda slumpmässigt (och inga oavgjorda) 55
The Microsoft Shuffle Microsoft antitrust probe by EU. Microsoft var överens om att visa en slumpmässig genererade skärm så att användare kunde välja sin browser i Windows 7. http://www.browserchoice.eu förekom sist 50% av tiden 56
The Microsoft Shuffle Lösningen? Implementera shuffle sort genom att skriva en comparator som alltid returnera ett slump svar. public int compareto(browser that) { Microsofts implementation i Javascript double r = Math.random(); function if (r RandomSort < 0.5) return (a,b) -1; { if (r > 0.5) return +1; return (0.50; - Math.random()); browser comparator (ska implementera en totalordning) 57
Knuth shuffle demo - Under iteration i, slumpa fram ett heltalr mellan 0 och i. - Swappaa[i] och a[r]. 58
Knuth shuffle - Under iteration i, slumpa fram ett heltal r mellan 0 och i. - Swappa a[i] och a[r]. Sats. [Fisher-Yates 1938] Knuth shuffle sort resulterar i en slumpmässig valda permutation (uniformly random permutation) av input array:n i linjär tid. Vi antar heltal valda slumpmässigt 59
Knuth shuffle - Under iteration i, slumpa fram ett heltal r mellan 0 och i. - Swappa a[i] och a[r]. vanlig bugg : mellan 0 and N 1 korrekt variant: mellan i and N 1 public class StdRandom {... public static void shuffle(object[] a) { int N = a.length; for (int i = 0; i < N; i++) { int r = StdRandom.uniform(i + 1); exch(a, i, r); mellan 0 och i 60
Trasig Knuth shuffle Vad händer om heltalet är vald mellan 0 och N-1? Det är inte slumpmässigt längre! istället för 0 och i permutation Knuth shuffle broken shuffle A B C 1/6 4/27 A C B 1/6 5/27 B A C 1/6 5/27 B C A 1/6 5/27 C A B 1/6 4/27 C B A 1/6 4/27 sannolikhet av alla resultat när man blandar { A, B, C 61
Online Poker Texas hold'em poker. Programmet ska blanda elektroniska kort. How We Learned to Cheat at Online Poker: A Study in Software Security http://www.datamation.com/entdev/article.php/616221 62
Online poker anekdot Shuffling algorithm in FAQ at www.planetpoker.com for i := 1 to 52 do begin r := random(51) + 1; swap := card[r]; card[r] := card[i]; card[i] := swap; end; between 1 and 51 Bug 1. Slump tal r aldrig 52 => 52 :de kort kan inte hamna i 52 :de platsen. Bug 2. Blandingen är inte slumpmässig (ska vara mellan 1 och i). Bug 3. random() använder bara en 32-bit seed => 2 32 möjliga blandningar. Bug 4. Seed = millisekunder sedan midnatt => 86.4 miljon blandningar. Exploit. Man kan, efter har set bara 5 kort och synkroniserat med server klockan, förutspå alla framtida kort i realtid. The generation of random numbers is too important to be left to chance. Robert R. Coveyou 63
Online poker: bästa praxis Bästa praxis för blandning. - Använd en hårdvara lösning som genererar slumptal som är godkänd för både både FIPS 140-2 och NIST statistiska prov. Men, hårdvara slumptal generatorer kan vara ömtåliga och kan fail silently". - Använd en opartiska blandningsalgoritm. 64
Sammanfattning Enkla algoritmer för att sortera arrayer - Selection sort - Insertion sort - Shell sort Blandning - Att blanda kort är svårt! Näst - N log N sorteringsalgoritmer baserad på divide-and-conquer - Mergesort och Quicksort