alternativer til sortering og søking binære trær søketrær Ikke-rekursiv algoritme som løser Hanois tårn med n plater

Like dokumenter
Dagens temaer. Sortering: 4 metoder Søking: binærsøk Rekursjon: Hanois tårn

Rekursjon. Binærsøk. Hanois tårn.

Rekursjon. Hanois tårn. Milepeler for å løse problemet

Dagens tema. Sortering. Fortsettelse om programmering vha tråder.

Dagens tema. Sortering. Fortsettelse om programmering vha tråder.

Hvorfor sortering og søking? Søking og sortering. Binære søketrær. Ordnet innsetting forbereder for mer effektiv søking og sortering INF1010 INF1010

En implementasjon av binærtre. Dagens tema. Klassestruktur hovedstruktur abstract class BTnode {}

Vanlige datastrukturer. I dette lysarksettet

INF1010. Om pensum INF1010 INF1010 INF1010 INF1010. Det vesentlige er å forstå og kunne lage programmer ved hjelp av eksemplene i bøkene.

Quicksort. Fra idé til algoritme.

INF1010 notat: Binærsøking og quicksort

INF1010 e-postadresser

Binære søketrær. Et notat for INF1010 Stein Michael Storleer 16. mai 2013

UNIVERSITETET I OSLO

INF1010 Rekursive metoder, binære søketrær. Algoritmer: Mer om rekursive kall mellom objekter Ny datastruktur: binært tre

EKSAMEN. Dato: 18. mai 2017 Eksamenstid: 09:00 13:00

Finne et personobjekt med et gitt navn. Sette personobjekt inn i treet

Algoritmer og datastrukturer Eksamen

EKSAMEN. Dato: 9. mai 2016 Eksamenstid: 09:00 13:00

Lenkelister. Lister og køer. Kopi av utvalgte sider fra forelesningen.

INF1010 siste begreper før oblig 2

INF1010 Binære søketrær ++

"behrozm" Oppsummering - programskisse for traversering av en graf (dybde først) Forelesning i INF februar 2009

Studieaktiviteter i INF1010

Binære søketrær. En ordnet datastruktur med raske oppslag. Sigmund Hansen

Rekursiv programmering

Datastrukturer for rask søking

Rekursiv programmering

INF1010 Sortering. Marit Nybakken 1. mars 2004

Dagens forelesning. INF1010 Datastrukturer Lister og køer Pekerkjedelister Øvelser. Innhold i dette lysarksettet

Oppgavesettet består av 7 sider, inkludert denne forsiden. Kontroll& at oppgaven er komplett før du begynner å besvare spørsmålene.

INF2220: Time 12 - Sortering

Søkeproblemet. Gitt en datastruktur med n elementer: Finnes et bestemt element (eller en bestemt verdi) x lagret i datastrukturen eller ikke?

INF2220: Forelesning 2

Definisjon av binært søketre

Operasjoner på lenkede lister (enkeltlenket) Eksempel på en lenket liste: personliste. INF januar 2010 (uke 3) 2

Sorteringsproblemet. Gitt en array A med n elementer som kan sammenlignes med hverandre:

Eks 1: Binærtre Binærtretraversering Eks 2: Binærtre og stakk

Løsnings forslag i java In115, Våren 1998

Løsnings forslag i java In115, Våren 1996

Rekursjon som programmeringsteknikk

Dagens tema INF1010 INF1010 INF1010 INF1010

Kapittel 8: Sortering og søking

Gjøre noe i hele treet = kalle på samme metode i alle objekten. Java datastruktur Klassestruktur

Hvor raskt klarer vi å sortere?

Velkommen til INF1010

UNIVERSITETET I OSLO

Lenkelister. Lister og køer.

Ny/utsatt EKSAMEN. Dato: 6. januar 2017 Eksamenstid: 09:00 13:00

Kapittel 9: Sortering og søking Kort versjon

UNIVERSITETET I OSLO

EKSAMEN med løsningsforslag

Endret litt som ukeoppgave i INF1010 våren 2004

Definisjon: Et sortert tre

INF110 Algoritmer og datastrukturer TRÆR. Vi skal i denne forelesningen se litt på ulike typer trær:

UNIVERSITETET I OSLO

... Når internminnet blir for lite. Dagens plan: Løsning: Utvidbar hashing. hash(x) katalog. O modellen er ikke lenger gyldig ved

Algoritmer og Datastrukturer

Kapittel 9: Sortering og søking Kort versjon

Dagens tema. INF Algoritmer og datastrukturer. Binærtrær. Generelle trær

Kap.8 Sortering og søking sist oppdatert 16.03

Algoritmer og datastrukturer Løsningsforslag

INF2220: Forelesning 1. Praktisk informasjon Analyse av algoritmer (kapittel 2) (Binær)trær (kapittel )

UNIVERSITETET I OSLO

EKSAMEN. Algoritmer og datastrukturer

UNIVERSITETET I OSLO

Løsningsforslag ukeoppg. 9: okt (INF Høst 2011)

Rekursjon. (Big Java kapittel 13) Fra Urban dictionary: recursion see recursion. IN1010 uke 8 våren Dag Langmyhr

Dagens forelesning. Java 13. Rollefordeling (variant 1) Rollefordeling (variant 2) Design av større programmer : fordeling av roller.

Algoritmer og datastrukturer Løsningsforslag

Kapittel 9: Sortering og søking Kort versjon

Algoritmer og Datastrukturer

UNIVERSITETET I OSLO

Binære trær: Noen algoritmer og anvendelser

Versjon (vil bli endret).

UNIVERSITETET I OSLO

Kapittel 8: Sortering og søking INF100

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

Oppgave 1 a. INF1020 Algoritmer og datastrukturer. Oppgave 1 b

UNIVERSITETET I OSLO

EKSAMEN. Dato: 28. mai 2018 Eksamenstid: 09:00 13:00

UNIVERSITETET I OSLO

Ny/utsatt EKSAMEN. Dato: 5. januar 2018 Eksamenstid: 09:00 13:00

Rekursjon. (Big Java kapittel 13) Fra Urban dictionary: recursion see recursion. IN1010 uke 8 våren Dag Langmyhr

Algoritmer og Datastrukturer

Løsningsforslag ukeoppg. 6: 28. sep - 4. okt (INF Høst 2011)

INF2220: Forelesning 2

Kapittel 8: Sortering og søking INF100

INF2220: Forelesning 2. Balanserte søketrær Rød-svarte trær (kapittel12.2) B-trær (kapittel 4.7)

INF Uke 10. Løsningsforslag ukesoppgaver oktober 2012

EKSAMEN Løsningsforslag. med forbehold om bugs :-)

Algoritmer og datastrukturer Løsningsforslag

Algoritmer og datastrukturer Kapittel 2 - Delkapittel 2.1

Forelesning inf Java 5

Repetisjon: Binære. Dagens plan: Rød-svarte trær. Oppgave (N + 1)!

Forelesning inf Java 5

PG4200 Algoritmer og datastrukturer Forelesning 7

Logaritmiske sorteringsalgoritmer

Lese fra fil. INF1000 : Forelesning 5. Eksempel. De vanligste lesemetodene. Metoder:

Transkript:

Dagens temaer Sortering: 4 metoder Hvorfor sortering (og søking) er viktig i programmering Sortering når objektene som skal sorteres er i et array 1. Sorterering ved bruk av binærtre som «mellomlager» Søking: binærsøk Binærsøk i et sortert heltallsarray Iterativ metode for binærsøk Rekursiv metode for binærsøk Rekursjon: Hanois tårn Noen milepæler i utviklingen av programmet Forstå spillet/problemet Om tårnet i Hanoi eller Hanois tårn Lage en plan for hva programmet skal gjøre (med ord) Ikke-rekursiv algoritme som løser Hanois tårn med n plater bottom-up programutvikling Rekursiv metode som kan flytte n plater Utvide programmet stegvis og teste for hvert steg Sortering når objektene som skal sorteres er i et array Forutsetter at vi kan rangere elementene. Gitt to elementer, programmet må kunne teste om det ene elementet er lik, mindre enn eller større enn det andre, jf. grensesnittet Comparable med metoden compareto... I eksemplene sorterer vi ofte enkle «objekter» som heltall, tegn eller strenger. Ikke vanskeligere å sortere komplekse objekter så lenge de er «sammenlignbare». Litt mer formaliteter: Med en sortert array mener vi en array (A) der A[0] A[1] A[2] A[3] A[n 2] A[n 1] Hvorfor sortering (og søking) er viktig i programmering «orden» i dataene vi blir fort lei av å lete poleksempel internett «alt» er søking og sortering alternativer til sortering og søking binære trær søketrær 1. Sorterering ved bruk av binærtre som «mellomlager» Programmeringsidé: Sett objektene inn i et binært søketre. Etter at alle er satt inn, ta dem ut i sortert orden (hvordan?) og sett dem inn i arrayet i sortert orden. Jasmina Imran Nikita Objekter som har navn som kommer alfabetisk foran (mindre enn) "Imran" Objekter hvor navn er større enn "Nikita"

1. Sorterering ved bruk av binærtre som «mellomlager» Henrik Andreas Christian Gry Darjan Eirik Gunnar Elisabeth Helge Henrik Jørgen Andreas Susanne Gunnar Nikita Jim Vivi Pål Elisabeth Christian Jørgen Darjan Eirik Jan Torjus Tor Gry Simen Stian Imran Nguyen Helge Philip Siv Imran Jan Jørgen Jim Susanne Nguyen Nikita Pål Philip Tor Simen Torjus Stian Vivi Slik blir treet hvis navnene kommer slik lista over er (fra øverst og nedover) Siv 2. Boblesortering Idé: Gå igjennom arrayet og for hver gang man finner to elementer ved siden av hverandre som ligger feil i forhold til sorteringskriteriet, bytt dem. Gjenta gjennomgangen til ingen bytter blir gjort. Påstand: Hvis det ikke finnes to elementer ved siden av hverandre som ikke oppfyller sorteringsregelen, må hele arrayen være sortert. Oppgave til plenumsøvelsen: implementer algoritmen. 1. Sorterering ved bruk av binærtre som «mellomlager» Andreas Christian Darjan Eirik Elisabeth Gry Gunnar Helge Henrik Imran Jan Jim Jørgen Nguyen Nikita Philip Pål Simen Siv Stian Susanne Tor Torjus Vivi Fra sortert liste (øverst) til binært søketre Jørgen Gunnar Stian Eirik Jan Pål Torjus Christian Elisabeth Henrik Jim Nikita Siv Susanne Vivi Andreas Darjan Gry Helge Imran Nguyen Philip Simen Tor 3. Flettesortering Algoritmeidé: Del arrayen opp i delarrayer, slik at hver delarray er sortert (et array med ett element er sortert). Flett sammen to og to arrayer til større sorterte delarrayer til det er et array igjen. 1 3 4 7 7 9 11 12 12 13 1 1 2 5 5 6 9 10 11 15 16 17 1 1 1 2 3 4 5 5 6 7 7 9 9 10 11 11 12 12 13 15 16 17 1 1 1 2 3 4 5 5 6 7 7 9 9 10 11 11 12 12 Oppgave til plenumsøvelsen: implementer algoritmen.

4. Innstikksortering Generell idé: Plukk ett og ett element fra listen og sett det inn på rett plass (sortert) i en ny liste. 1. Finn første element fra venstre som er mindre enn det til venstre for seg ta dette ut. 2. Elementene til venstre for dette skyves mot høyre inntil det uttatte elementet passer inn. 3. Gjenta 1 2 inntil det siste elementet (helt til høyre) er behandlet. Invariant:A[0 :k] er sortert forksom løper fra 0 til lengden ava 1. Innstikksortering: variant Generell idé: Plukk ut det minste elementet og sett det inn bakerst (FIFO) i en ny liste/array. 1. Finn det minste elementet i arrayen ta dette ut. 2. Sett det uttatte elementet i fifo-orden inn i et nytt array. 3. Gjenta 1 2 inntil det siste elementet i det første arrayet er tatt ut. Invariant? Oppgave til plenumsøvelsen: implementer algoritmen. I programeksemplet nedenfor sorteres et array av tegn, char[] a. 1 void innstikksortering( char [ ] a) { 2 for ( int k = 0; k < a. length 1; k++) { 3 if (a[k + 1] < a[k ] ) { 4 // a[k + 1] står på f e i l plass 5 char tmp = a[k + 1]; 6 int i = k; 7 while ( i >= 0 && a[ i ] > tmp) { 8 // a[ i ] > tmp, flytt t i l høyre 9 a[ i + 1] = a[ i ] ; 10 i ; 11 } 12 // sett tmp på rett plass 13 a[ i +1] = tmp; 14 } 15 } 16 } Binærsøk i et sortert heltallsarray Effektiv søking i en sortert array I et heltallsarraya[]mednelementer skal vi finne en indeks (objektet) hvor verdien erk.a[]er sortert slik at A[i 1] A[i], mao. i stigende orden fra 0 og oppover: A[0] A[1] A[2] A[3] A[n 2] A[n 1] Hva bør vi gjøre hvis k < A[0] eller k > A[n 1]? Hvis A[0] k A[n 1] har vi følgende idé for algoritme: Sjekk omker større enn, mindre enn, eller lik elementet midt i arrayen. Hvis ikke lik, «kast» den halvdelen som k ikke kan være i.

Iterativ metode for binærsøk Iterativ metode som leter etter talletk. Returnererks indeks hvis funnet, 1 ellers. 1 int binarsok ( int [ ] a, int fra, int til, int k) { 2 int midten; boolean funnet = false ; 3 while ( funnet == false ) { 4 if ( fra > t i l ) { 5 return 1; 6 } else { 7 midten = ( fra + t i l ) / 2; 8 if (k == a[midten ] ) { 9 return midten; 10 } else if (k < a[midten ] ) 11 t i l = midten 1; 12 else fra = midten+1; 13 } 14 } 15 } Noen milepæler i utviklingen av programmet Løsning av Hanois tårn. Milepeler Forstå spillet Bestemme/skjønne hvordan spillet løses Lage en plan for hva programmet skal gjøre (med ord) Lage en programskisse (tegning og kvasikode) Dele opp problemet i deler som kan gjøres for seg Kompilere og test første del Utvide programmet stegvis og teste for hvert steg Rekursiv metode for binærsøk Rekursiv metode som leter etter talletk. Returnererks indeks hvis funnet, 1 ellers. 1 int binarsok ( int [ ] a, int fra, int til, int k) { 2 int midten; 3 if ( fra > t i l ) { 4 return 1; 5 } else { 6 midten = ( fra + t i l ) / 2; 7 if (k == a[midten ] ) { 8 return midten; 9 } else if (k < a[midten ] ) { 10 return binarsok ( a, fra, midten 1, k ) ; 11 } else { // k > a[midten ] 12 return binarsok (a, midten+1, til, k ) ; 13 } 14 } 15 } Forstå spillet/problemet Illustrasjonen er hentet fra www.wikipedia.org Bare en plate kan flyttes om gangen Platen som flyttes må flyttes til en av de andre pinnene En plate kan ikke legges over en mindre plate

Om tårnet i Hanoi eller Hanois tårn Legenden Hindutempel med 3 påler, 64 gullplater med hull i midten Når alle 64 plater er flyttet til en annen påle vil templet og verden gå under Minst 18.446.744.073.709.551.615 enkeltflyttinger Edouard Lucas 1883 Spillet Det finnes flere algoritmer Lage en plan for hva programmet skal gjøre (med ord) Metoden som kan flytte tre plater lages slik: Vha metoden som kan flytte 2 plater flytter vi disse til pinne 2 (via). Så flytter vi den største plata (nr 3) fra pinne 1 (fra) til pinne 3 (til). Til sist flytter vi de 2 platene fra pinne 2 (via) til pinne 3 (til) vha metoden som kan flytte 2. Så lager vi en ny metode som kan flytte 4 plater. Denne bruker metoden vi nettopp laget som kan flytte 3 plater. Slik fortsetter vi, til vi har laget metoden som flytter så mange plater som vi ønsker. I følge legenden 64. Først ser vi på en alternativ løsning fra nettet: Lage en plan for hva programmet skal gjøre (med ord) Løsningen av spillet er en liste av trekk eller enkeltflytninger. Et trekk er entydig bestemt hvis det angis fra hvilken pinne det flyttes til hvilken pinne, siden det bare er lov å flytte platen som ligger øverst. Hvis de tre pinnene heter 1 (fra), 2 (via), og 3 (til). Og spillet går ut på å flytte to plater fra pinne 1 til pinne 3, er løsningen denne lista med 3 enkeltflytninger: Flytt en plate fra 1 til 2 Flytt en plate fra 1 til 3 Flytt en plate fra 2 til 3 Lag først en metode som kan flytte en plate. Lag så en som kan flytte to plater vha den første. Så en som kan flytte tre plater. Ikke-rekursiv algoritme som løser Hanois tårn med n plater Definerer en positiv retning: P1 P2 P3 P1 hvis antall plater er et ulikt tall P1 P3 P2 P1 hvis antall plater er et partall Algoritme: Gå i løkke: 1. Flytt den minste platen en pinne i postiv retning 2. Gjør det eneste andre lovlige trekket (enkeltflytt) som ikke involverer den minste platen. Avslutt løkka hvis 2 ikke var mulig, hvis 2 kunne gjøres, fortsett slutt

Ikke-rekursiv algoritme som løser Hanois tårn med n plater I kvasikode: while (!ferdig ) { 1. Flytt den minste platen en pinne i postiv retning 2. Hvis mulig, gjør det lovlige trekket mellom de to andre p (ikke pinnen med den minste platen) Hvis trekk 2 ikke var mulig { ferdig = true } } Det er lett å lage en datamodell og et javaprogram som utfører algoritmen ved å angi hvilke enkeltflytt som skal gjøres. Det er derimot vanskelig å skjønne at dette programmet løser Hanois tårn mednplater. (Beviset for det går langt utover det vi skal lære i INF1010. Interesserte kan finne bevis på nettet, f.eks. http://www.cs.yorku.ca/ andy/courses/3101/lecture-notes/ln0.html) 1 public static void flytt64 ( int fra, int t i l, int via ) { 2 flytt63 ( fra, via, t i l ) ; 3 flytt1 ( fra, til, via ) ; 4 flytt63 ( via, til, fra ) ; 5 } 6 7 public static void flytt1 ( int fra, int t i l, int via ) { 8 System. out. println ( Flytter en plate fra : 9 + fra + t i l : + t i l ) ; 10 } 11 12 public static void flytt63 ( int fra, int t i l, int via ) {... } Først skriver vi et program som løser det legendariske problemet med 64 plater. 64 er mer konkret enn n og lettere å forholde seg til. Vi vet allerede nå at løsningen på oppgaven er en sekvens (liste) av (lovlige) flytt. Lage en metode som kan flytte 64 plater ved hjelp av to andre metoder: 1. en metode som kan flytte en plate 2. en metode som kan flytte 63 plater Hvis flytt63 gjør det den skal vil dette virke. Vi må da programmere flytt63, og gjør det over samme lest: 1 public static void flytt63 ( int fra, int t i l, int via ) { 2 flytt62 ( fra, via, t i l ) ; 3 flytt1 ( fra, til, via ) ; 4 flytt62 ( via, til, fra ) ; 5 } Vi skjønner mønsteret (vi trenger flytt62, flytt61,..., flytt2 også) og hvis vi behersker en teksteditor godt, bruker vi ikke lang tid på å lage programmet:

1 public static void flytt64 ( int fra, int t i l, int via ) { 2 flytt63 ( fra, via, t i l ) ; 3 flytt1 ( fra, til, via ) ; 4 flytt63 ( via, til, fra ) ; 5 } 6 7 public static void flytt63 ( int fra, int t i l, int via ) { 8 flytt62 ( fra, via, t i l ) ; 9 flytt1 ( fra, til, via ) ; 10 flytt62 ( via, til, fra ) ; 11 }... Denne måten å utvikle programmet på (vi bruker metoder vi ikke har programmert ennå) kalles top-down, siden vi begynner i den komplekse enden (løser problemet for 64 plater og antar vi har metoder som løser de enklere oppgavene før vi har laget dem). lag først en metode som kan flytte 64 plater (vha flytt63) så en som kan flytte 63 ved hjelp av den som kan flytte 62 så en som kan flytte 62...... så en som kan flytte 2 ved hjelp av en som kan flytte 1 tilslutt den som flytter 1 plate 1 2 // 60 metoder utelatt ( flytt62... tilogmed... flytt3 ) ) 3 4 public static void flytt2 ( int fra, int t i l, int via ) { 5 flytt1 ( fra, via, t i l ) ; 6 flytt1 ( fra, til, via ) ; 7 flytt1 ( via, til, fra ) ; 8 } 9 10 public static void flytt1 ( int fra, int t i l, int via ) { 11 System. out. println ( Flytter en plate fra : 12 + fra + t i l : + t i l ) ; 13 } bottom-up programutvikling Vi kan også tenke omvendt. Den utviklingsmetoden kalles bottom-up: lag først en metode som kan flytte 1 plate ved hjelp av den lager vi metoden som kan flytte 2 så en som kan flytte 3 ved hjelp av metoden som flytter 2... så en som kan flytte 63 ved hjelp av den som kan flytte 62 tilslutt en som kan flytte 64 Programmet blir det samme uansett utviklingsmetode.

Rekursiv metode som kan flytte n plater Mens vi har laget 64 nesten like metoder, har vi fått ideen om å la antall plater som skal flyttes være en parameter til metoden, la oss kalle antalletn, og de tre pinnene henholdsvis frapinnen, tilpinnen og viapinnen: 1. flyttn 1 plater fra frapinnen til viapinnen 2. flytt 1 plate fra frapinnen til tilpinnen 3. flyttn 1 plater fra viapinnen til tilpinnen Hvis algoritmen klarer å flytten 1 plater riktig, skulle dette fungere fornplater (vi har programmert slik). Vi sørger så for at metoden virker forn=1 (basistilfellet) og metoden vil være korrekt (ved induksjon). Vi skriver algoritmen i java: Utvide programmet stegvis og teste for hvert steg Hva er basistilfellet og er de rekursive kallene nærmere dette? Hvordan representerer vi pinner og plater i programmet (datamodellen)? Vi har her utviklet et program som lager en liste over enkeltflytninger som må gjøres for å løse oppgaven. En naturlig utvidelse (er vi nå bottom-up eller top-down?) er at vi ønsker at vi istedet skal se trekkene bli utført grafisk på skjermen. Til det trenger vi et utsyn som kan tegne opp de tre pålene eller pinnene, med platene på. Da kan det kanskje være hensiktsmessig å ha en modell av situasjonen i spillet. Ved å kalle på en passende metode i utsynet fikk vi så tegnet situasjonen på skjermen. I stedet for å skrive ut enkeltflytningene, kan man lage kommandoer (metodekall) til modellen som foretar den tilsvarende endringen. I dette eksemplet er datamodellen så enkel, at det er lett å klare seg uten en egen modellklasse og la utsynet lese datastrukturen direkte. Rekursiv metode som kan flytte n plater 1 public static void flytt ( int ant, int fra, int til, int via ) { 2 if ( ant == 0) { 3 } else { 4 flytt ( ant 1, fra, via, t i l ) ; 5 flytt1 ( fra, t i l ) ; 6 flytt ( ant 1, via, til, fra ) ; 7 } 8 } 9 10 public static void flytt1 ( int fra, int t i l ) { 11 antallflytt++; 12 System. out. println ( Flytter en plate fra pinne 13 + fra + t i l pinne + t i l ) ; 14 } Utvide programmet stegvis og teste for hvert steg En annen naturlig utvidelse er å la brukeren få velge antall plater i spillet. Vi kan også tenke oss muligheten av at brukeren får spille spillet ved å angi hvilken plate som skal flyttes. Hvis andre har laget en spesifikasjon (eller prekode) er det på dette stadiet (når vi vet vi har løst selve kjernen av problemet) naturlig å se på denne igjen og starte med å innarbeide den til et ferdig program.