ID1020:Enkel Sortering Dr. Jim Dowling [email protected] kap 2.1 Slides adapted from Algorithms 4th Edition, Sedgewick. Ett sorteringsproblem • T.ex. Student poster på ett universitet. post nyckel Chen 3 A 991-878-4944 308 Blair Rohde 2 A 232-343-5555 343 Forbes Gazsi 4 B 766-093-9873 101 Brown Furia 1 A 766-093-9873 101 Brown Kanaga 3 B 898-122-9643 22 Brown Andrews 3 A 664-480-0023 097 Little 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 contacts FedEx packages 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; Insertion.class 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.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 datatyp implementation 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 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 mindre än (returnera -1) v w lika med (returnera 0) w v 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; } public int compareTo(Date that) if (this.year < that.year ) if (this.year > that.year ) if (this.month < that.month) if (this.month > that.month) if (this.day < that.day ) if (this.day > that.day ) return 0; } { jämför Date objekt bara med andra Date objekt { return return return return return return -1; +1; -1; +1; -1; +1; } 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. int min = i; for (int j = i+1; j < N; j++) { if (less(a[j], a[min])) { min = j; } } i slutordning 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. 2. antalet jämförelser (comparisons) antalet byten (exchanges) • Om algoritmen inte swappar element, då räknar vi antalet array accesser. 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. 2 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. AE ELMOPRSTX • 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. XTS RPOMLF EA 33 Insertion sort: delvis sorterade arrayer • Def. En inversion är ett par nycklar som är i fel ordningen. AE ELMOTRXPS 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. ACH H I MN N PQXYKBINARY 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 A E L E O P M S X R T • Varför insertion sort? - Stora inkrement ⇒ small subarray. - Små inkrement ⇒ nästan sorterad. 39 Shellsort exempel: inkrement av 7, 3, 1 input S O R T E X A M P L E 1-sort A E L E O P M S X R T A E L E O P M S X R T 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 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 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 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 algoritm position h-sorted nuvarande subsekvens http://www.sorting-algorithms.com/shell-sort andra element 43 Shellsort: animering 50 delvis sorterade poster algoritm position h-sorted nuvarande subsekvens http://www.sorting-algorithms.com/shell-sort 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 E O L M E X A E E L M O X A E E L M O X A A E L E O X M A E L E O X M A E L E O P M A E L E O P M A E L E O P M A E L E O P M S P S P S P S P S P S P S X S X S X S X R R R R R R R R R R T T T T T T T T T 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. R, bzip2, /linux/kernel/groups.c • Användbart i praktiken. - Snabb om array:n inte är enorm. - Mycket liten minneskomplexitet (använt i vissa inbyggda system). uClibc • Enkel algoritm, icke-trivial prestanda, intressanta frågor. - Asymptotisk tidskomplexitet? - Bästa möjliga sekvens av inkrementet? öppet problem: - Average-case prestanda? 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 N2 N2 N2 insertion sort N N2 N2 Shellsort (3x+1) N log N ? Mål N N 3/2 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 (a,b) if (rRandomSort < 0.5) return -1; { if (r > 0.5) return +1; return return (0.5 0; - 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 ABC 1/6 4/27 ACB 1/6 5/27 BAC 1/6 5/27 BCA 1/6 5/27 CAB 1/6 4/27 CBA 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; • • • • Bug Bug Bug Bug 1. 2. 3. 4. between 1 and 51 Slump tal r aldrig 52 => 52:de kort kan inte hamna i 52:de platsen. Blandingen är inte slumpmässig (ska vara mellan 1 och i). random() använder bara en 32-bit seed => 232 möjliga blandningar. 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