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