1 / 22

Grundlæggende programmering Efterår 2001

Grundlæggende programmering Efterår 2001. Forelæsning 11 onsdag 14/11 2001 kl. 9:15 – 12:00. Dagens program. Søgning og sortering. Søgning og sortering. Motivation Anvendelser Hvorfor er et ok at kun kikke på heltal? Algoritmer vs. programmer Effektivitet af programmer

levi
Download Presentation

Grundlæggende programmering Efterår 2001

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Grundlæggende programmeringEfterår 2001 Forelæsning 11 onsdag 14/11 2001 kl. 9:15 – 12:00

  2. Dagens program • Søgning og sortering

  3. Søgning og sortering • Motivation • Anvendelser • Hvorfor er et ok at kun kikke på heltal? • Algoritmer vs. programmer • Effektivitet af programmer • måles i forhold til antal elementer der skal søges iblandt, eller som skal sorteres. • Effektivitet af algoritmer: et mål som er relativt til andre algoritmer, og ikke i forhold til antal sekunder i den virkelige verden. • Hvis vi skal søge i en mængde på 1.000.000 tal, kan der være en faktor 25.000 til forskel mellem en simpel løsning og den bedste løsning.

  4. Simpel lineær søgning Hvis vi har følgende tabel: og ønsker at finde ud af om 62 er med, og på hvilken position det så i givet fald er, må man starte i den ene ende og lede. Når vi er et stykke inde i søgningen, kunne situationen beskrives som: 22 15 44 33 9 72 37 25 53 47 19 45 11 62 39 27 3 59 13 81 50 Dette er ikke gennemsøgt Dette er gennemsøgt 22 15 44 33 9 72 37 25 53 47 19 45 11 62 39 27 3 59 13 81 50 index

  5. Bedste, gennemsnits og værste tilfælde I gennemsnit skal vi lede halvdelen af tabellen igennem for at finde elementet, og hele tabellen hvis det ikke er med. Hvis tabellen er n elementer stor, så siger vi at vi i værste tilfælde skal foretage n sammenligninger, mens vi i bedste tilfælde skal foretage 1 sammenligning, og i gennemsnit n/2 sammenligninger. Dette er ikke gennemsøgt Dette er gennemsøgt 22 15 44 33 9 72 37 25 53 47 19 45 11 62 39 27 3 59 13 81 50 index

  6. En bedre måde. Hvis tallene stod i rækkefølge . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 3 9 11 13 15 19 22 25 27 33 37 39 44 45 47 50 53 59 62 72 81 Så kunne vi starte med at sammeligne 62 med det tal i midten af tabellen (position 11, tallet 33). 62 er større end 37, hvorfor det må være til højre for 37. Vi vælger så det midterste mellem index 11 og 21 = 16. 62 er større end 50, og vi vælger det midterste mellem 16 og 21 = 18. 62 er større end 59, og vi vælger det midterste mellem 18 og 21, som er 19. Og 62 står netop på plads 19. Denne gang brugte sammenlignede vi med 37, 50, 59 og 62. Altså 4 gange. Metoden kaldes binær søgning fordi man bisekterer tabellen hver gang. Den er god fordi man ved hver sammenligning undgår at lede i den ene halvdel af elementerne. Så der er mange man slet ikke behøver at sammenligne med. 20

  7. Hvor god er binær søgning Hvis vi ved hver sammenligning kan smide halvdelen af elementerne fra, hvor mange gange skal vi så halvere før man kun har et element tilbage? Altså, hvis man har n, hvor mange gange kan man halvere n før man er nede på 1. Man kan sørge omvendt, hvor mange gange skal vi fordoble 1 før vi kommer op på mindst n? (1) 1*2 = 2 (9) 256*2=512 (2) 2*2 = 4 (10) 512*2=1024 (3) 4*2 = 8 (11) 1024*2=2048 (4) 8*2 = 16 ... (5) 16*2 = 32 (20) ...= 1.048.576 (6) 32*2 = 64 (23) ... = 8.388.608 (større end antal danskere) (7) 64*2 = 128 (30) ... = 1.073.741.824 (8) 128*2= 256 (33) ... = 8.589.934.592 (større end antal mennesker)

  8. Lidt logaritme gejl Antal gange vi skal sammenligne k i en tabel med n elementer er altså givet ved at være det mindste heltal k sådan at: 2k >= n Og det finder man altså ved: k = log2(n) (sådan er logaritmer defineret!) På en lommeregner er der ikke en log2 funktion, men den kan udregnes med en almindelig logaritme som: k = log(n)/log(2) I vores eksempel var der 21 elementer. log(21)/log(2) = 4.39232 Det vil sige at vi i værste tilfælde skal halvere 5 gange, d.v.s. sammenligne med 5 tal.

  9. Sortering God søgning kræver at tabellen er sorteret. Derfor er sortering vigtig. Ofte vil man nemlig søge mange gange i samme tabel, og det er derfor vigtigt at kunne søge effektivt.

  10. Udvælgelses sortering 22 15 44 33 9 72 37 25 53 47 19 45 11 62 39 27 3 59 13 81 50 usorteret Find mindste element, og flyt det forrest. 3 15 44 33 9 72 37 25 53 47 19 45 11 62 39 27 22 59 13 81 50 sorteret usorteret Find mindste element i den usorterede, og flyt det forrest i den usorterede del. 3 9 44 33 15 72 37 25 53 47 19 45 11 62 39 27 22 59 13 81 50 sorteret usorteret

  11. Udvælgelses sortering er håbløs For at sortere n elementer, skal vi i værste tilfælde bruge følgende antal sammenligninger og ombytninger. Første gang skal vi sammenligne med (n-1) elementer, og 1 byt. Anden gang skal vi sammenligne med (n-2) elementer og 1 byt. Tredje gang skal vi sammenligne med (n-3) elementer og 1 byt. ... I alt: n+(n-1)+(n-2)+...3+2. Hvis vi stiller det første og sidste led sammen, det andet og andet sidste osv, får vi følgende: (n+2) + ((n-1)+3) + ((n-2)+4)... = (n+2) + (n+2) + (n+2) ... ialt n/2 led på formen (n+2). Dvs summen er i alt n(n+2)/2 = n2/2 + n. For store n er det lidt ligegyldigt med n, og man siger derfor at udvælgelses sortering er n2. For n = 1000 giver den rigtige formel 501000, mens den skønsmæssige giver 1000000.

  12. Den er rigtig håbløs Hvis man kan sammenligne 1.000.000 elementer på et sekund, hvor lang tid tager det så at sortere alle danskere efter personnummer? Der er godt 5.000.000 danskere. 5.000.0002= 25.000.000.000.000, som divideret med 1.000.000 pr sekund giver 25.000.000 sekunder. Som er cirka 9 måneder og 20 dage.

  13. En bedre måde: Quicksort Dette er en utrolig god ide, som er fundet på af en af de helt store inden for datalogi (C.A.R. Hoare, 1959) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 15 44 33 9 72 37 25 53 47 19 45 11 62 39 27 3 59 13 81 50 usorteret Vi vælger et tilfældigt element i tabellen – f.eks. det midterste (19), og om ordner tabellen i to dele, en del som indeholder alle tal der er mindre end eller lig 19, og en del er er større end 19. Dette kaldes opdelingsfasen i quicksort. 3 15 11 9 13 19 37 25 53 47 33 45 44 62 39 27 22 59 72 81 50 <= 19 >= 19 Sorter hver del for sig selv. Dette kan gøres rekursivt. 3 9 11 13 15 19 22 25 27 33 37 39 44 45 47 50 53 59 62 72 81

  14. Quicksort: 2 pegere 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 13 15 3 33 9 72 37 25 53 47 19 45 11 62 39 27 44 59 22 81 50

  15. Opdelingsfasen i quicksort 3 15 11 9 13 19 37 25 53 47 33 45 44 50 39 27 22 59 72 81 62 pivottal=62 while (lilleIndex <= storIndex) { while (tabel[lilleIndex]<pivotTal) lilleIndex++; while (tabel[storIndex]>pivotTal) storIndex++; if (lilleIndex <= storIndex) { swap(tabel, lilleIndex, storIndex); lilleIndex++; storIndex--; } }

  16. Quicksort videre 3 15 11 9 13 19 37 25 53 47 33 45 44 62 39 27 22 59 72 81 50 3 9 11 15 13 19 37 25 22 27 33 39 44 62 45 47 53 59 72 81 50 <= 11 >11, <= 19 >19, <= 44 >44 3 9 11 15 13 19 27 25 22 37 33 39 44 50 45 47 53 59 72 81 62 3 9 11 15 13 19 22 25 27 37 33 39 44 45 50 47 53 59 62 81 72

  17. Hvor god/dårlig er quicksort I bedste tilfælde. I hver opdelingsfase løbes tabellen igennem en gang, og hvert element sammenlignes med pivottallet en gang. Hvis vi er mega heldige finder vi et pivottal der opdeler i to lige store dele. Man kan som sagt dele op i halvdele i alt log2(n) gange før man står tilbage med enkelt elementer. Dvs. at vi kan dele op log2(n), og hver gang skal vi igennem en opdelingsfase der koster n sammenligninger. I alt n log2(n). Hvis vi har vores 5.000.000 Danskere, så bliver det cirka 5.000.000*24 = 120.000.000 sammenligninger som med 1.000.000 pr. sekund giver 120 sekunder = 2 minutter. I værste tilfælde Så opdeler vi i del med et element, og en med n-1 elementer = som den dårlige.

  18. Gennemsnits quicksort Quicksort er i gennemsnit ret god. I en tilfældig opdeling vil man dele op i to dele, hvor man deler op i en ¼ og en på ¾ af den oprindelige længde. Hvor mange gange skal man dele en op i ¾ før man når ned på et element? Ja, man kan dele op i ¾ i alt log4/3(n) gange. Så hvis vi har vores 5.000.000 danskere, så er log4/3(5.000.000) = log(5.000.000)/log(4/3) = 53,6 eller cirka 54 gange. I gennemsnit er quicksort altså cirka halvt så god som i bedste tilfælde.

  19. Hele quicksort Det er denne metode vi kalder. Den kalder så den rekursive udgave, idet den skal have nogle index som parameter. public int[] quicksort(int[] tabel){ return quicksort(tabel,0, tabel.length-1); } private int[] quicksort(int[] tabel, int startIndex, int slutIndex){ if (startIndex<slutIndex){ int lilleIndex=startIndex; int storIndex=slutIndex; int pivotTal= tabel[(startIndex+slutIndex)/2]; while (lilleIndex <= storIndex) { while (tabel[lilleIndex]<pivotTal) lilleIndex++; while (tabel[storIndex]>pivotTal) storIndex--; if (lilleIndex <= storIndex) { swap(tabel, lilleIndex, storIndex); lilleIndex++; storIndex--; } } quicksort(tabel,startIndex,storIndex); quicksort(tabel,lilleIndex,slutIndex); } return tabel; } private void swap(int[] tabel, int a, int b){int t=tabel[a]; tabel[a]=tabel[b]; tabel[b]=t;}

  20. Fletningsbaseret sortering (mergesort) 22 15 44 33 9 72 37 25 53 47 19 45 11 62 39 27 3 59 13 81 50 sorter hver halvdel for sig 9 15 22 25 33 37 44 47 53 72 3 11 13 19 27 39 45 50 59 62 81 flet de to halvdele 3 9 11 13 15 19 22 25 27 33 37 39 44 45 47 50 53 59 62 72 81

  21. Sorter en halvdel, kvarte, ... 22 15 44 33 9 72 37 25 53 47 22 15 44 33 9 sorter hver kvart for sig sorter hver kvart for sig 15 22 9 33 44 9 15 22 33 44 25 37 47 53 72 flet de to kvarte flet de to kvarte 9 15 22 33 44 9 15 22 25 33 37 44 47 53 72 44 33 9 sorter to tal 44 9 33 flet 9 33 44

  22. Divide-and-conquer • Grundideen bag mergesort (del-og-hersk, divide-and-conquer): For at sortere en tabel med n tal i, gør følgende: • del tabellen i to halvdele; • sorter begge halvdele hver for sig; • flet de to halvdele sammen som et (“skævt”) lynlås. • (Se efterfølgende – mere om søgning og sortering næste gang).

More Related