66
1 Sortering

Sortering

  • Upload
    hashim

  • View
    29

  • Download
    0

Embed Size (px)

DESCRIPTION

Sortering. Plan. Elementære metoder til sortering -sortering ved indsættelse -Shellsort Sorteringsmetoder baseret på rekursion quicksort flettesortering Randomisering. - PowerPoint PPT Presentation

Citation preview

Page 1: Sortering

1

Sortering

Page 2: Sortering

2

Plan

• Elementære metoder til sortering

- sortering ved indsættelse

- Shellsort

• Sorteringsmetoder baseret på rekursion– quicksort– flettesortering

• Randomisering

Page 3: Sortering

3

Hvorfor sortere?

(1) Det er lettere at søge i en en sorteret datamængde end i en usorteret datamængde, såvel for maskiner som for mennesker.

Tænk f.eks. på opslag i en telefonbog.

(2) Mange problemer kan løses mere effektivt, hvis inddata er sorteret.

Eksempel: Hvis to filer er sorteret i samme orden, er det muligt i blot

ét gennemløb at finde alle de poster, der findes i begge filer.

Uformel definition: Ved sortering forstås en proces, hvorved elementerne i en datamængde ordnes i rangfølge.

Page 4: Sortering

4

Bestemmelse af fællesmængden for to usorterede arrays

k = 0;for (i = 0; i < M; i++) for (j = 0; j < N; j++) if (a[i] == b[j])

c[k++] = a[i];

Kompleksitet: O(M * N)

i

a:M0

jb:

0 N

kc:

0

Page 5: Sortering

5

i = j = k = 0;while (i < M && j < N) if (a[i] < b[j]) i++; else if (a[i] > b[j]) j++; else { c[k++] = a[i]; i++; j++; }

Bestemmelse af fællesmængden for to sorterede arrays

Kompleksitet: O(M + N)

i

a:M0

<

jb:

0 N<

kc:

0

<

Page 6: Sortering

6

Permutationer

En permutation af en mængde af objekter er en ordning af objekterne.

For eksempel er p = (2 3 1) en permutation af {1, 2, 3}.

p(1) = 2 p(2) = 3 p(3) = 1

Der er 6 permutationer af {1, 2, 3}, nemlig (1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1)

Antallet af permutationer af n objekter er n!.

Page 7: Sortering

7

Lad der desuden være defineret en ordningsrelation ‘<’ på mængden af nøgleværdier, som er total, dvs. for vilkårlige tre nøgleværdier a, b og c opfylder følgende to betingelser:

(1) Præcis et af følgende 3 udsagn er sandt: a < b, a = b eller b < a (3-delelighed)

(2) Hvis a < b og b < c, så a < c (transitivitet)

Lad der være givet N emner R1, R2, ..., RN, der skal sorteres. Vi kalder dem poster, og hele samlingen kaldes for en fil. Hver post Ri indeholder en nøgle, Ki, til styring af sorteringen. Herudover kan en post indeholde anden information.

En sortering af en fil af n poster er en permutation, p, af mængden {1, 2, ..., n}, som ordner nøglerne i stigende rækkefølge:

Kp(1) ≤ K p(2) ≤ ... ≤ Kp(N).

Page 8: Sortering

8

En sortering af en fil i det indre lager (f.eks. et array), kaldes for intern sortering.

En sortering af en fil på et eksternt lagermedium (f.eks. en disk) kaldes for ekstern sortering.

Terminologi

Page 9: Sortering

9

Elementære algoritmer

Sortering ved indsættelseShellsort

Hvorfor studere elementære algoritmer?

(1) De er lette at kode

(2) De er (tilstrækkeligt) hurtige for små filer

(3) I specielle situationer er de hurtigst

(4) Udgør illustrative eksempler på algoritmedesign og -analyse

Page 10: Sortering

10

Problem: Givet et array a med elementerne a[0], a[1], ..., a[n-1]. Sorter elementerne i stigende orden.

Sortering ved indsættelse

Løsning (ved induktion):

Basistilfælde: Vi ved, hvordan 1 element sorteres.Induktionshypotese: Vi ved, hvordan n-1 elementer sorteres.

Vi kan opnå en sortering af n elementer ved (1) at sortere de første n-1 elementer, (2) indsætte det n´te element korrekt blandt disse.

Page 11: Sortering

11

A S O R T I N G E X A M P L E

A S O R T I N G E X A M P L E

A O S R T I N G E X A M P L E

A O R S T I N G E X A M P L E

A O R S T I N G E X A M P L E

A I O R S T N G E X A M P L E

A I N O R S T G E X A M P L E

A G I N O R S T E X A M P L E

A E G I N O R S T X A M P L E

A E G I N O R S T X A M P L E

A A E G I N O R S T X M P L E

A A E G I M N O R S T X P L E

A A E G I M N O P R S T X L E

A A E G I L M N O P R S T X E

A A E E G I L M N O P R S T X

Page 12: Sortering

12

void insertionSort(Comparable[] a, int i) {

if (i > 0) {

insertionSort(a, i - 1);

for (int j = i;

j > 0 && a[j].compareTo(a[j - 1]) < 0; j--)

swap(a, j, j - 1);

}

}

Sortering ved indsættelse (rekursiv udgave)

void swap(Object[] a, int i, int j) {

Object tmp = a[i]; a[i] = a[j]; a[j] = tmp;

}

Page 13: Sortering

13

void insertionSort(Comparable[] a) {

for (int i = 1; i < a.length; i++)

for (int j = i;

j > 0 && a[j].compareTo(a[j - 1]) < 0; j--)

swap(a, j, j - 1);

}

Sortering ved indsættelse(iterativ udgave)

Page 14: Sortering

14

void insertionSort(Comparable[] a, int i) {

for (int i = 1; i < a.length; i++){

Comparable tmp = a[i];

int j = i;

for ( ; j > 0 && tmp.compareTo(a[j - 1]) < 0; j--)

a[j] = a[j - 1];

a[j] = tmp;

}

}

Sortering ved indsættelse (iterativ udgave med flytninger)

tmp:

i

a:

0 j-1 j

Page 15: Sortering

15

Animering af sortering ved indsættelse

Page 16: Sortering

16

Analyse af sortering ved indsættelse

Antal sammenligninger:

Bedste tilfælde: n-1

Værste tilfælde: 1 + 2 + ... + (n-1) = n(n-1)/2 = O(n2)

Gennemsnitlige tilfælde: n(n-1)/4 = O(n2)

Antal flytninger:

Bedste tilfælde: 0

Værste tilfælde: 1 + 2 + ... + (n-1) = n(n-1)/2 = O(n2)

Gennemsnitlige tilfælde: n(n-1)/8 = O(n2)

Tidsforbruget er lineært for “næsten sorterede” filer.

Page 17: Sortering

17

Shellsort(D. L. Shell, 1959)

Ide: Sortering ved indsættelse er meget effektiv, når filen er “næsten sorteret”. Men for “meget usorterede” filer er den langsom, da den kun tillader ombytning af naboelementer.

Spørgsmål: Kan vi sørge for at ombytte elementer, der ligger langt fra hinanden i starten, for så derefter at foretage en sædvanlig sortering ved indsættelse?

Svar: Ja, vi kan sortere de delfiler, der fås ved at tage hvert h´te element i den oprindelige fil, hvor h > 1.

Page 18: Sortering

18

4-sortering

1. Opdel filen i 4 delfiler: hvert 4. element startende i det første, hvert 4. element startende i det andet, hvert 4. element startende i det tredje, hvert 4. element startende i det fjerde,

2. Sorter hver af disse.

Filen siges da at være 4-sorteret.

På tilsvarende måde kan vi definere en h-sortering.

Bemærkning: En fil, der er 1-sorteret, er sorteret.

Page 19: Sortering

19

4-sortering ved indsættelseBenyt sortering ved indsættelse med “skridtlængde” 4.

A S O R T I N G E X A M P L E

A S O R T I N G E X A M P L E

A I O R T S N G E X A M P L E

A I N R T S O G E X A M P L E

A I N G T S O R E X A M P L E

A I N G E S O R T X A M P L E

A I N G E S O R T X A M P L E

A I A G E S N R T X O M P L E

A I A G E S N M T X O R P L E

A I A G E S N M P X O R T L E

A I A G E L N M P S O R T X E

A I A G E L E M P S N R T X O

Page 20: Sortering

20

h-sortering

void h_sort(Comparable[] a, int h) { for (int i = h; i < a.length; i++) { Comparable tmp = a[i]; int j = i; for ( ; j >= h && tmp.compareTo(a[j - h]) < 0; j -= h)

a[j] = a[j - h]; a[j] = tmp; }}

I forhold til insertionSort er 1 blot erstattet med h.

Page 21: Sortering

21

void shellsort(Comparable[] a) { int h; for (h = 1; h < a.lenghth / 9; h = 3 * h + 1) ; for ( ; h >= 1; h /= 3)

h_sort(a, h);}

Shellsort

Shellsort er h-sortering for en aftagende sekvens af h-værdier, afsluttende med h = 1.

I dette tilfælde sekvensen ..., 1093, 364, 121, 40, 13, 4, 1.

Det er en god ide, at vælge sekvenser, hvor successive værdier er indbyrdes primiske (deres største fælles divisor er 1).

Page 22: Sortering

22

void shellsort(Comparable[] a) {

for (int h = a.length / 2;

h > 0; h = h == 2 ? 1 : h / 2.2)

h_sort(a, h);

}

Shellsort

Lærebogens algoritme:

Page 23: Sortering

23

Animering af Shellsort

Page 24: Sortering

24

Analyse af Shellsort

Antal sammenligninger:

Bedste tilfælde: (n-1) + (n-4) + (n-13) + ... ≤ n log3n

Værste tilfælde: højst n1.5 (for sekvensen 1, 4, 13, ...)

Gennemsnitlige tilfælde: kendes ikke. To forslag er O(n1.25) og O(n(log n)2).

Antal flytninger:

Bedste tilfælde: 0

Værste tilfælde: højst n1.5 (for sekvensen 1, 4, 13, ...)

Gennemsnitlige tilfælde: kendes ikke. To forslag er O(n1.25) og O(n(log n)2).

Page 25: Sortering

25

Java (JIT), tid i sekunder:

metode N = 32000 64000 128000 256000 512000 1024000

insertionSort 6.59 27.24 114.14 - - -

shellsort 0.04 0.08 0.18 0.41 1.03 2.37

Måling af køretider(PowerBook G3, 400 MHz, Metrowerks)

C, tid i sekunder:

metode N = 32000 64000 128000 256000 512000 1024000insertionSort 3.02 12.70 32.22 - - -shellsort 0.03 0.05 0.13 0.35 0.80 1.97

Page 26: Sortering

26

Har du brug for en sorteringsmetode?

Så brug Shellsort.

• lidt kode

• bedste metode til små og middelstore filer

• stadig OK for meget store filer

Page 27: Sortering

27

Quicksort(C. A. R. Hoare, 1962)

Quicksort er i praksis den hurtigste algoritme til intern sortering.

Ide: For at sortere et array, så del det i en venstre og en højre del, således at alle elementer i den venstre del er mindre end eller lig med alle elementer i den højre del.

Sorter derefter den venstre del og den højre del rekursivt.

venstre del højre del

Page 28: Sortering

28

Deling (partition)

Delingen af et array a kan foretages således:

(1) Vælg en delingsværdi, v, blandt værdierne i a.

(2) Gennemløb a fra venstre mod højre, indtil der findes et element a[i] ≥ v.

(3) Gennemløb a fra højre mod venstre, indtil der findes et element a[j] ≤ v.

(4) Ombyt a[i]og a[j].

(5) Fortsæt med at gennemløbe og ombytte, indtil de to gennemløb “krydser” hinanden.

≤ v ≥ va[i] a[j]

Page 29: Sortering

29

v: delingsværdieni: venstre-mod-højre-pegerenj: højre-mod-venstre-pegeren

i j

≤ v ≥ v

a[i] ≥ v a[j] ≤ v

X Y

i j

≤ v ≥ vY X

≤ v ≥ v

Page 30: Sortering

30

Deling af a[low:high] med hensyn til v:

i = low; j = high; while (i <= j) { while (a[i].compareTo(v) < 0) i++; while (a[j].compareTo(v) > 0) j--; if (i <= j) { swap(a, i, j); i++; j--; } }

Implementering

Resultat: a[low:i] ≤ a[j:high] og i > j.

Kan bevises ved at påvise gyldigheden af løkkeinvarianten { a[low:i-1] ≤ v ≤ a[j+1:high] } for den yderste løkke.

Page 31: Sortering

31

void quicksort(Comparable[] a, int low, int high) { if (low < high) { Comparable v = a[(low + high)/2]; int i = low, j = high;

while (true) { while (a[i].compareTo(v) < 0) i++; while (a[j].compareTo(v) > 0) j--; if (i >= j) break; swap(a, i, j); i++; j--; } quicksort(a, low, j); quicksort(a, i, high); } }

Quicksort

Delingsværdien v (også kaldet pivot-værdien) kan være værdien af et vilkårligt element blandt a[low:high], f.eks. a[(low+high)/2].

Page 32: Sortering

32

int partition(Comparable[] a, int low, int high) {

Comparable v = a[high];

int i = low - 1, j = high;

while (true) {

while (a[++i].compareTo(v) < 0) ;

while (v.compareTo(a[--j]) < 0)

if (j == low) break;

if (i >= j) break;

swap(a, i, j);

}

swap(a, i, high);

return i;

}

Alternativ implementering af delingen

Vi kan alternativt anvende a[high] som delingsværdi. a[low:high-1] deles, hvorefter a[high] ombyttes med a[i].

Page 33: Sortering

33

int quicksort(Comparable[] a, int low, int high) {

if (low < high) {

int i = partition(a, low, high);

quicksort(a, low, i - 1);

quicksort(a, i + 1, high);

}

}

Metoden quicksort

Page 34: Sortering

34

Animering af quicksort

Page 35: Sortering

35

Antal sammenligninger

Lad C(N) betegne antallet af sammenligninger ved kald af quicksort med N elementer.

Ved delingen foretages cirka N sammenligninger. Herefter sorteres den venstre del og den højre del hver for sig.

I gennemsnit består hver del af cirka N/2 elementer, og får vi derfor rekursionsrelationen:

C(N) = N + 2*C(N/2) for N ≥ 2, og C(1) = 0.

som har løsningen

C(N) = N log2N.

Page 36: Sortering

36

Mere præcise beregninger giver

Quicksort bruger i gennemsnit cirka 2N lnN sammenligninger.

hvor ln betegner den naturlige logaritme.

Antal sammenligninger i gennemsnit

2N ln N ≈ 1.38 N log2N

Det gennemsnitlige antal sammenligninger er altså kun 38% højere end antallet af sammenligninger i det bedste tilfælde.

Page 37: Sortering

37

Antal sammenligninger i værste tilfælde

Det værste tilfælde optræder, når delingen for hvert N resulterer i en del med 1 element og en del med N-1 elementer.

Vi få da C(N) = N + C(N-1), for N ≥ 2, og C(1) = 0.

som har løsningen C(N) = N(N+1)/2.

Det værste tilfælde optræder, når filen er sorteret (eventuelt i omvendt orden).

Valg af tilfældigt delingselement (eller “median af 3”) reducerer chancen for, at det værste tilfælde optræder.

Page 38: Sortering

38

void quicksort(Comparable[] a, int low, int high) {

if (low < high) {

if (a[high].compareTo(a[low]) < 0)

swap(a, low, high);

int mid = (low + high)/2;

if (mid == low) return;

if (a[mid].compareTo(a[low]) < 0)

swap(a, low, mid);

if (a[high].compareTo(a[mid]) < 0)

swap(a, mid, high);

swap(a, mid, high - 1);

int i = partition(a, low + 1, high - 1);

quicksort(a, low, i - 1);

quicksort(a, i + 1, high);

}

}

Quicksort med median af 3

Page 39: Sortering

39

Benyt en simpel metode for små delfiler

if (high - low < CUTOFF) insertionSort(a, low, high);

else

indsættes i stedet for

if (low < high)

i starten af quicksort, hvor CUTOFF f.eks. er 10.

Page 40: Sortering

40

Tid i sekunder:

Metode N = 32000 64000 128000 256000 512000 1024000

quicksort 0.03 0.05 0.09 0.17 0.36 0.76

shellsort 0.04 0.08 0.18 0.41 1.03 2.37

insertionSort 6.59 27.24 114.14 ≈ 8 min ≈ 32 min ≈ 2 timer

quicksort: median af 3 og insertionSort for små delfiler (CUTOFF = 10).

Empirisk undersøgelse af quicksort

(PowerBook G3, 400 MHz, Metrowerks)

Page 41: Sortering

41

Udvælgelse

Problem: Find det k’te mindste element blandt en mængde af N elementer.

Eksempel: Det 3. mindste tal blandt {3, 6, 5, 2, 8, 4} er 4.

Løsningsmulighed 1: Sorter elementerne i stigende orden. Det k´te element i den sorterede rækkefølge er løsning på problemet.

Kompleksitet: afhænger af sorteringsmetode - med quicksort: O(N log N).

Page 42: Sortering

42

Løsningsmulighed 2: Hvis k er lille, så anvend sortering ved udvælgelse, men stop, når de første k elementer er på plads.

Kompleksitet: O(k N),

idet N + (N-1) + … + (N - k + 1) ≈ k N

Løsningsmulighed 3: Anvend en “hob” (en datastruktur til repræsentation af prioritetskøer - mere herom senere).

Kompleksitet: O(k log N)

Kan vi gøre det bedre?

Page 43: Sortering

43

Udvælgelse ved brug af partition

Metoden omordner a, så a[low:k-1] ≤ a[k] ≤ a[k+1:high].

void quickSelect(Comparable[] a, int low, int high, int k) { if (low < high) { int i = partition(a, low, high); if (i > k) quickSelect(a, low, i - 1, k); if (i < k) quickSelect(a, i + 1, high, k); } }

Da der kun benyttes halerekursion, kan rekursionen let elimineres:

void quickSelect(Comparable a[], int low, int high, int k) { while (low < high) { int i = partition(a, low, high); if (i >= k) high = i - 1; if (i <= k) low = i + 1; } }

Page 44: Sortering

44

O(N) i gennemsnit,

idet N + N/2 + N/4 + … ≤ 2N.

Det er muligt (men ikke helt let) at sørge for garanteret lineær køretid.

Kompleksitet af quickSelect

Page 45: Sortering

45

void sort(Comparable[] a, int low, int high) { if (low < high) {

// Del: Del a[low:high] i to delfiler, a[low:i] og a[j:high], hvor i ≥ j.// Hersk: sort(a, low, i);

sort(a, j, high);// Kombiner: Sammensæt de to sorterede delfiler, så de udgør en sortering af a[low:high].

}}

Sortering ved del-og-hersk

Mergesort (sortering ved fletning):Del: i = (low+high)/2; j = i+1; Kombiner: Flet de to sorterede delfiler, og placer resultatet i a[low:high].

Quicksort: Del: Vælg en værdi, v. Ombyt elementerne i a[low:high], således at a[low:i] ≤ v ≤ a[j:high], og i ≥ j. Kombiner: Intet.

Page 46: Sortering

46

Fletning

for (i = j = k = 0; k < M + N; k++) if (i >= M) c[k] = b[j++]; else if (j >= N) c[k] = a[i++]; else c[k] = a[i].compareTo(b[j]) < 0 ? a[i++] : b[j++];

kc:

0 M+N≤

i

a:

M0

≤ ≤

jb:

0 N≤ ≤

Page 47: Sortering

47

mergeSort

void mergeSort(Comparable[] a, int low, int high) { if (low < high) { int mid = (low + high)/2; mergesort(a, low, mid); mergesort(a, mid + 1, high); merge(a, low, mid, high); }}

Page 48: Sortering

48

void merge(Comparable[] a, int low, int mid, int high) { int i = low, j = mid + 1; for (int k = low; k <= high; k++) if (i > mid) b[k] = a[j++]; else if (j > high) b[k] = a[i++]; else b[k] = a[i].compareTo(a[j]) < 0 ? a[i++] : a[j++]; for (int k = low; k <= high; k++) a[k] = b[k];}

Fletning af a[low:mid] med a[mid+1:high] over i a[low:high]:

Simpel fletning

low mid mid + 1 high

≤ ≤a:

≤b:

low high

Fletning:

≤a:

low high

Kopiering:

Page 49: Sortering

49

A S O R T I N G E X A M P L E

A S O R T I N G E X A M P L E

A S O R T I N G E X A M P L E

A O R S T I N G E X A M P L E

A O R S I T N G E X A M P L E

A O R S I T G N E X A M P L E

A O R S G I N T E X A M P L E

A G I N O R S T E X A M P L E

A G I N O R S T E X A M P L E

A G I N O R S T E X A M P L E

A G I N O R S T A E M X P L E

A G I N O R S T A E M L L P E

A G I N O R S T A E M L E L P

A G I N O R S T A E E L M P X

A A E E G I L M N O P R S T X

Page 50: Sortering

50

Animering af mergesort

Page 51: Sortering

51

Kaldtræer

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

2 2 2 2 2 2 2 2

4 4 4 4

88

16

1 1 1 2 1 1 1 2 1 1 1 2 1 2 1 2

2 3 2 3 2 3 3 3

5 5 5 6

1110

21

1 1 1 1 1 1 1 11 1

Page 52: Sortering

52

Vurdering af sortering ved fletning

Fordele:

• er ufølsom over for startorden i inddata

• kræver cirka N log2N sammenligninger for at sortere enhver fil C(N) = 2C(N/2) + N, C(1) = 0

• er stabil

• kan benyttes til at sortere lister

• er velegnet til ekstern sortering

Ulemper:

• kræver (i praksis) ekstra plads proportional med N

Page 53: Sortering

53

At en metode er stabil kan være hensigtsmæssigt ved sortering på flere nøgler.

Hans 9 Arne 9 Jørgen 03Karen 11 Erling 11 Mette 7Jørgen 03 Hans 9 Niels 7Niels 7 Jørgen 03 Arne 9Mette 7 Karen 11 Hans 9Arne 9 Mette 7 Erling 11Erling 11 Niels 7 Karen 11

Sorter på første nøgle. Derefter på anden.For samme anden nøgle bevares rækkefølgen for ens nøgler fra første sortering.

Stabile metoder

En sorteringsmetode siges at være stabil, hvis den bevarer den relative orden af poster med samme nøgle i filen.

Page 54: Sortering

54

Tid i sekunder:

Metode N = 32000 64000 128000 256000 512000 102400

mergesort 0.06 0.12 0.25 0.54 1.15 2.67

quicksort 0.03 0.05 0.09 0.17 0.36 0.76

shellsort 0.04 0.08 0.18 0.41 1.03 2.37

Empirisk undersøgelse af mergesort

Page 55: Sortering

55

Uformelt bevis:Sortering er ækvivalent med bestemmelse af en permutation. Sortering kan derfor modelleres ved et beslutningstræ, hvor hver interne knude svarer til en sammenligning af to nøgler, mens hver eksterne knude svarer til en af de N! mulige permutationer. Højden i dette træ er mindst log2(N!).

Af Stirlings formel

fås log2(N!) ≈ Nlog2N - 1.44N.

Kompleksiteten af sortering

Enhver sorteringsalgoritme, der er baseret på nøglesammenligninger, kræver i værste tilfælde mindst cNlog2N sammenligninger for at sortere N elementer, hvor c er en konstant > 0.

N! ≈ 2πN(Ne)N

Page 56: Sortering

56

Kriterier for valg af sorteringsmetode

• Størrelse af nøgler (sammenligninger)

• Størrelse af poster (flytninger/ombytninger)

• Størrelse af fil (elementær/avanceret metode)

• Nøgletype (sammenligninger/radix)

• Mange ens nøgler?

• Er filen næsten sorteret?

• Kræves stabilitet?

Page 57: Sortering

57

Randomisering

Page 58: Sortering

58

Behovet for tilfældige tal

Mange anvendelser:

• Programafprøvning (generering af tilfældige inddata)

• Sortering (f.eks. bestemmelse af pivot-elementet i quicksort)

• Simulering (f.eks. generering af kunders ankomst til en bank)

• Spil (f.eks. valg af åbningstræk)

• Randomiserede algoritmer (f.eks. test af om et tal er et primtal)

Page 59: Sortering

59

Generering af tilfældige tal

Ægte tilfældighed på en computer er umuligt at opnå.

Vi må nøjes med pseudotilfældige tal, d.v.s. tal der forekommer at være tilfældige.

Sekvenser af genererede tal skal kunne modstå en lang række statistiske tests.

For det meste benyttes en lineær kongruens generator (Lehmer, 1951):

Xi+1 = AXi + B (mod M)

hvor Xi+1, Xi, A, B og M er heltal.

X0 kaldes for generatorens sæd.

A, B og M skal vælges således, at længden af en sekvens (perioden) bliver så lang som muligt. M bør være et stort primtal.

Page 60: Sortering

60

Generering af tilfældige tal i Java

Java tilbyder klassen java.util.Random.

public class Random { public Random(); public Random(long seed); public int nextInt(); public long nextLong(); public float nextFloat(); public double nextDouble(); public double nextBytes(byte[] bytes); public double nextGaussian(); public void setSeed(long seed); protected int next(int bits);}

Page 61: Sortering

61

public class Random { private long seed; private final static long multiplier = 0x5DEECE66DL; // = 25214903917 private final static long addend = 0xBL; // = 11 private final static long mask = (1L << 48) - 1; public Random() { this(System.currentTimeMillis()); } public Random(long seed) { this.seed = (seed ^ multiplier) & mask; } public int nextInt() { return next(32); } protected int next(int bits) { long nextseed = (seed * multiplier + addend) & mask; seed = nextseed; return (int) (nextseed >>> (48 - bits)); }}

Til generering af tilfældige heltal benyttes Lehmers metode

Page 62: Sortering

62

Generering af tilfældige permutationer(kan f.eks. benyttes til blanding af kort)

void permute(Object[] a) { Random r = new Random(); for (int i = 1; i < a.length; i++) swap(a, i, r.nextInt(i + 1));}

Page 63: Sortering

63

• Læs kapitel 10 og 11

• Løs følgende opgaver

Opgave 20: 8.2 (1 point) Opgave 21: 8.11 (2 point) Opgave 22: Se de næste sider (4 - 6 point, ikke-obligatorisk)

Afleveringsfrist: tirsdag den 6. november

Ugeseddel 623. oktober - 30. oktober

Page 64: Sortering

64

fortsættes

På næste side er angivet et udkast til en klasse, OneWayList, til håndtering afenvejslister. Hvert element i en envejsliste har en reference til sin efterfølger. Interntrepræsenteres elementerne ved hjælp af den private, statiske klasse Node. Et objekt,header, af denne klasse udgør et hoved for listen.

Spørgsm ål 1Programm er metoderne addFirst og isEmpty.addFirst(obj) skal tilføje objektet obj forrest i listen.isEmpty skal returnere true, hvis listen er tom; ellers false.

Spørgsm ål 2Programm er klassen OneWayListIterator.

Spørgsm ål 3Programm er metoden reverse, der skal vende om på rækkefølgen af listens elementer.M etodens lagerforbrug bør være konstant, og altså uafhængigt af listens længde.

Spørgsm ål 4Programm er de to udgaver af m etoden sort. Kaldet sort() skal bevirke, at listens ele-menter sorteres i stigende orden, dog kun under forudsætning af, at de alle tilhører enklasse, der implementerer grænsefladen Comparable. Et kald af sort(comp) skal be-virke, at listens elementer sorterer ifølge Comparator-objektet comp.

M etodernes lagerforbrug m å ikke være O(n) eller mere. Det er således ikke tilladt atbruge et hjælpe-array til sorteringen.

Benyt f.eks. sortering ved udvælgelse (tidskompleksitet O(n2)). En implementering, derbenytter sig af sortering ved fletning (tidskom pleksitet O(n log n)), belønnes med 2ekstrapoint.

NB. Udkastet til klassen kan m ed fordel hentes fra kursets hjemm eside via henvisningen"Kode til opgaver".

Page 65: Sortering

65

fortsættes

import java.util.*;

public class OneWayList { public OneWayList() { header = new Node(null, null); }

public void addFirst(Object obj) { /* se spørgsmål 1 */ }

public boolean isEmpty() { /* se spørgsmål 1 */ }

public Iterator iterator() { return new OneWayListIterator(); }

public void reverse() { /* se spørgsmål 3 */ }

public void sort() { /* se spørgsmål 4 */ }

public void sort(Comparator comp) { /* se spørgsmål 4 */ }

public String toString() { String result = ""; Iterator it = iterator(); while (it.hasNext()) result += it.next() + " "; return result.trim(); }

private static class Node { Node(Object data, Node next) { this.data = data; this.next = next; } Object data; Node next; }

private class OneWayListIterator implements Iterator { /* se spørgsmål 2 */ }

private final Node header;}

Page 66: Sortering

66

Et simpelt testprogram er angivet nedenfor.

public static void main(String args[]) { OneWayList list = new OneWayList(); Random rand = new Random(7913); for (int i = 0; i < 10; i++) list.addFirst(new Integer(rand.nextInt(100))); System.out.println("Original:\n" + list); list.sort(); System.out.println("Sorted: \n" + list); list.reverse(); System.out.println("Reversed:\n" + list);

}