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

Like dokumenter
INF1010. Rekursjon En rekursiv definisjon av rekursjon, slik det kunne stå i en ordbok: Introduksjon til Rekursiv programmering

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

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

UNIVERSITETET I OSLO

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

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

UNIVERSITETET I OSLO

Seminaroppgaver IN1010, uke 2

Hva er verdien til variabelen j etter at følgende kode er utført? int i, j; i = 5; j = 10; while ( i < j ) { i = i + 2; j = j - 1; }

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

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

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

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

INF1010. Sekvensgenerering Alle mulige sekvenser av lengde tre av tallene 0, 1 og 2: Sekvensgenerering. Generalisering. n n n! INF1010 INF1010 INF1010

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

INF1010 Binære søketrær ++

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

2 Om statiske variable/konstanter og statiske metoder.

Endret litt som ukeoppgave i INF1010 våren 2004

Gjennomgang prøveeksamen oppgave 1, 2, 4, 5, 7

INF1010 LISTER. Listeelementer og listeoperasjoner. Foran. Bak

UNIVERSITETET I OSLO

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

INF1000 Behandling av tekster

2 Om statiske variable/konstanter og statiske metoder.

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

EKSAMEN med løsningsforslag

INF1000 EKSTRATILBUD. Stoff fra uke 1-5 (6) 3. oktober 2012 Siri Moe Jensen

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

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

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

UNIVERSITETET I OSLO

Oppsummering. Kort gjennomgang av klasser etc ved å løse halvparten av eksamen Klasser. Datastrukturer. Interface Subklasser Klasseparametre

Algoritmer og datastrukturer Løsningsforslag

Algoritmer og Datastrukturer

UNIVERSITETET I OSLO

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

INF1010 Sortering. Marit Nybakken 1. mars 2004

Av Stein Gjessing, Institutt for informatikk, Universitetet i Oslo

INF1000 (Uke 15) Eksamen V 04

INF1000 (Uke 15) Eksamen V 04

i=0 Repetisjon: arrayer Forelesning inf Java 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker 0*0 0*2 0*3 0*1 0*4

Forelesning inf Java 4

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

INF1010 siste begreper før oblig 2

Rekursiv programmering

Konstruktører. Bruk av konstruktører når vi opererer med "enkle" klasser er ganske ukomplisert. Når vi skriver. skjer følgende:

Algoritmer og datastrukturer Løsningsforslag

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

Sortering med tråder - Quicksort

INF1010 Eksamenstips. Løsningsforslag prøveeksamen del 1.

INF1010, 22. mai Prøveeksamen (Eksamen 12. juni 2012) Stein Gjessing Inst. for Informatikk Universitetet i Oslo

UNIVERSITETET I OSLO

INF2220: Forelesning 7. Kombinatorisk søking

Innhold uke 4. INF 1000 høsten 2011 Uke 4: 13. september. Deklarasjon av peker og opprettelse av arrayobjektet. Representasjon av array i Java

UNIVERSITETET I OSLO

Vanlige datastrukturer. I dette lysarksettet

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

Rekursjon som programmeringsteknikk

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

LITT OM OPPLEGGET. INF1000 EKSTRATILBUD Stoff fra uke September 2012 Siri Moe Jensen EKSEMPLER

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

Algoritmer og datastrukturer Kapittel 3 - Delkapittel 3.1

Algoritmer og datastrukturer Kapittel 9 - Delkapittel 9.1

Uke 8 Eksamenseksempler + Ilan Villanger om studiestrategier. 11. okt Siri Moe Jensen Inst. for informatikk, UiO

INF1010 notat: Binærsøking og quicksort

Oppgave 3 a. Antagelser i oppgaveteksten. INF1020 Algoritmer og datastrukturer. Oppgave 3. Eksempelgraf

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

Algoritmer og datastrukturer Eksamen

Dagens tema: INF2100. Syntaksanalyse. Hva annet gjør en kompilator? Sjekking av navnebruk. Testutskrifter

Kompilering Statiske Syntaksanalyse Feilsjekking Eksempel Oppsummering

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

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

UNIVERSITETET I OSLO

Eksamen iin115, 14. mai 1998 Side 2 Oppgave 1 15 % Du skal skrive en prosedyre lagalle som i en global character array S(1:n) genererer alle sekvenser

OPPGAVE 1 OBLIGATORISKE OPPGAVER (OBLIG 1) (1) Uten å selv implementere og kjøre koden under, hva skriver koden ut til konsollen?

3 emner i dag! INF1000 Uke 5. Objekter og pekere. null. Litt om objekter, pekere og null Filer og easyio Litt mer om tekster

EKSAMEN. Algoritmer og datastrukturer

IN våren 2019 Onsdag 16. januar

IN våren 2018 Tirsdag 16. januar

UNIVERSITETET I OSLO

INF 1010, vår 2005 Løsningsforslag uke 11

INF1000 : Forelesning 4

Dagens tema: 12 gode råd for en kompilatorskriver

Algoritmer og datastrukturer Løsningsforslag

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

Post-it spørsmål fra timen (Arv og subklasser)

INF1010, 15. januar time. Parametriserte klasser (generiske klasser) Stein Gjessing Inst. for Informatikk Universitetet i Oslo

i=0 i=1 Repetisjon: nesting av løkker INF1000 : Forelesning 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker j=0 j=1 j=2 j=3 j=4

København 20 Stockholm

Norsk informatikkolympiade runde

UNIVERSITETET I OSLO

Kapittel 12: Rekursjon

UNIVERSITETET I OSLO

Inf 1000 høst 2005 Løsningsforslag ordinær eksamen

Syntaksanalyse. Dagens tema: Språkdiagrammene Jernbanediagrammene er et ypperlig utgangspunkt for å analysere et program: INF2100 INF2100 INF2100

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

Introduksjon til objektorientert programmering

Transkript:

Rekursiv programmering BTeksempel Datastruktur I klassen Persontre (rotperson==<hele treet>) Rekursjon Noen oppgaver/problemer er rekursive «av natur» Eksempel på en rekursiv definisjon Fakultetsfunksjonen Metoder som kaller seg selv Vertikal utskrift Hele programmet Oppsummering Finne maksimal verdi i en array Fibonaccitallene 4. rekursjonsregel Traversering Oppsummering - programskisse for traversering av en graf (dybde først) Rekursjonsreglene Rekursive metoder Datastruktur rotperson kristhk andrepar snorrewb kimst mariubac behrozm wenjinl bohalvor Et objekt av klassen Persontre Datastruktur 1 abstract class BTnode { 2 BTnode venstre, høyre ; 3... 4 } 5 class Person extends BTnode { 6 String navn; 7... 8 } BTnode venstre BTnode høyre class Person extends BTnode String navn behrozm "behrozm" I klassen Persontre (rotperson==<hele treet>) 1 public void settinn ( Person inn ) { 2 if ( rotperson == null ) rotperson = inn ; 3 else settinnrek ( inn, rotperson ) ; 4 System. out. print ( inn.hentnavn ( ) ) ; 5 System. out. print ( " " ) ; 6 } 7 8 private void settinnrek ( Person inn, Person tre ) { 9 int smnlgn = tre. sammenlign( inn ) ; 10 if ( smnlgn < 0 ) { 11 if ( tre.høyre == null ) tre.høyre = inn ; 12 else settinnrek ( inn, (Person ) tre.høyre ) ; 13 } 14 else if ( smnlgn > 0 ) { 15 if ( tre. venstre == null ) tre. venstre = inn ; 16 else settinnrek ( inn, (Person ) tre. venstre ) ; 17 } 18 }

Noen oppgaver/problemer er rekursive «av natur» rekursjon subst. -en. Hvis du har forstått hva rekursjon er, slutt å lese. Hvis ikke, se rekursjon. I Bokmålsordboka er rekursjon definert som periodisk gjentakelse. Oppgaver som er rekursive av natur kan ofte deles opp i flere deloppgaver der en eller flere av deloppgavene er svært lik den opprinnelige oppgaven. Å lage en definisjon eller et program av en slik oppgave er enkelt. Eksempel på en rekursiv definisjon 2 «grener»: 1. personen har bodd minst 20 år i Bergen og vi stanser undersøkelsen (basistilfelle) 2. Personen har ikke bodd minst 20 år i Bergen og vi må fortsette undersøkelsen på moren (rekursjon) Ikke rekursiv definisjon: En bergenser er en person som har bodd minst 20 år i Bergen, eller som har en mor som er bergenser, eller som har en mormor som er bergenser, eller som har en mormormor som er bergenser, eller som har en mormormormor som er bergenser, eller... Definisjon av en bregne En bregne er en stilk med bregner på. Eksempel på en rekursiv definisjon Definisjon av bergenser Oppgave: Finn ut om en gitt person er bergenser. En bergenser er en person som har bodd minst 20 år i Bergen, eller som har en mor som er bergenser. Oppgaven, undersøkelsen stopper enten fordi vi i støter på en person som har bodd mer enn 20 år i Bergen, eller fordi vi ikke finner (har en peker) til moren til den vi nå undersøker Hvisn=7, skal vi finne produktet av regnestykket 1 2 3 4 5 6 7= Vi gir metoden navnetf, den er av type int og har en parameternav type int: 1 2 int f ( int n) {... } f(1)=1 f(2)=1 2=2 f(3)=1 2 3=6 f(4)=1 2 3 4=24

f(5)=f(4) 5=24 5=120 f(6)=f(5) 6=120 6=720 f(n)=1 2 3 4... (n 1) n f(n)=f(n 1) n Den siste formelen er en rekursiv definisjon av metodenf. Det er denne vi benytter når vi skal programere rekursivt: 1 int f ( int n) { 2 int svar ; 3 i f (n == 1) svar = 1; 4 else svar = f (n 1) * n; 5 return svar ; 6 } prompt> java fakultet 7 f(7) = 5040 For bedre å se hva som skjer, legger vi inn testutskrift når metoden starter og før den avslutter. 1 int f ( int n) { 2 int svar ; 3 4 System. out. println ( " testutskrift : f ( "+n+" ) er kalt " ) ; 5 6 i f (n == 1) svar = 1; 7 else svar = f (n 1) * n; 8 9 System. out. println ( " testutskrift : f ( " + n + 10 " ) returnerer verdien " + svar ) ; 11 12 return svar ; 13 } 1 class fakultet { 2 3 public static void main( String [ ] args ) { 4 fakultet dd = new fakultet ( ) ; 5 int argument = Integer. parseint ( args [ 0 ] ) ; 6 i f ( argument < 1) argument = 1; 7 System. out. println ( " f ( " + argument + " ) = " 8 + dd. f (argument ) ) ; 9 } 10 11 int f ( int n) { 12 int svar ; 13 i f (n == 1) svar = 1; 14 else svar = f (n 1) * n; 15 return svar ; 16 } 17 } prompt> java fakultet 4 testutskrift: f(4) er kalt testutskrift: f(3) er kalt testutskrift: f(2) er kalt testutskrift: f(1) er kalt testutskrift: f(1) returnerer verdien 1 testutskrift: f(2) returnerer verdien 2 testutskrift: f(3) returnerer verdien 6 testutskrift: f(4) returnerer verdien 24 f(4) = 24 Dette går bra, fordi nårf(k 1) kalles, forsvinner ikke (instansen av metoden) kalletf(k). Sistnevnte overlater kontrollen tilf(k 1), «går i dvale» og «våkner opp igjen» nårf(k 1) avsluttes og returnerer med en verdi.

n = 5; main ( args[] = "5") svar = n * f(4); dd.f(5); n = 4; n = 1; svar = n * f(3); svar = 1; return 1; n = 3; n = 2; svar = n * f(2); svar = n * f(1); Test av programmet medn=5 gir følgende «resultat»: prompt> java fakultet 5 tstutskr: f(5) er kalt og går i dvale... tstutskr: f(4) er kalt og går i dvale... tstutskr: f(3) er kalt og går i dvale... tstutskr: f(2) er kalt og går i dvale... tstutskr: f(1) er kalt og returnerer verdien 1 tstutskr: f(2) våkner opp og returnerer verdien 2 tstutskr: f(3) våkner opp og returnerer verdien 6 tstutskr: f(4) våkner opp og returnerer verdien 24 tstutskr: f(5) våkner opp og returnerer verdien 120 f(5) = 120 Her kunne vi si enda mer i detf(k) våkner opp, f.eks. hvilken verdi som kom ut av det rekursive kalletf(k 1). Vi legger inn testutskrifter før det rekursive kallet: 1 int f ( int n) { 2 int svar ; 3 4 System. out. print ( " tstutskr : f ( "+ n +" ) er kalt og " ) ; 5 6 i f (n == 1) svar = 1; 7 else { 8 System. out. println ( " går i dvale... " ) ; 9 10 svar = f (n 1) * n; 11 12 System. out. print ( " tstutskr : f ( "+ n +" ) våkner opp og " ) ; 13 } 14 15 System. out. println ( " returnerer verdien " + svar ) ; 16 return svar ; 17 } Vertikal utskrift Et program som skriver ut en tekststreng «vertikalt», dvs. ett tegn per linje (println). 1 void skriv ( String s) { 2 while ( s. length ( ) > 0) { 3 System. out. println ( s. substring (0,1)); 4 // Husk å kaste utskrevet tegn 5 s = s. substring (1,s. length ( ) ) ; 6 } 7 } Delopppgavene: skriv ut tekststrengens første tegn skriv ut resten av teksstrengen

Vertikal utskrift 1 void skriv ( String s) { 2 if ( s. length ( ) == 1) System. out. println ( s ) ; 3 else { 4 // Mer enn e t t tegn, skriver ut første 5 System. out. println ( s. substring (0,1)); 6 // Kapper av utskrevet tegn 7 s = s. substring (1,s. length ( ) ) ; 8 // Da gjenstår bare å skrive ut resten. 9 // Vi sender med samme parameter, 10 // siden s nå er er e t t tegn kortere. 11 skriv ( s ) ; 12 } 13 } Hele programmet 1 class vertprint { 2 void skriv ( String s) { 3 if ( s. length ( ) == 1) System. out. println ( s ) ; 4 else { 5 System. out. println ( s. substring (0,1)); 6 // Kapper av utskrevet tegn 7 s = s. substring (1,s. length ( ) ) ; 8 skriv ( s ) ; 9 } 10 } 11 12 public static void main( String [ ] args ) { 13 vertprint vp = new vertprint ( ) ; 14 String argument = args [ 0]; 15 if (argument. length ( ) > 0) 16 vp. skriv (argument ) ; 17 else return ; 18 } 19 } Vertikal utskrift En test av programmet kan se slik ut: prompt> java vertprint rekursjon r e k u r s j o n prompt> Oppsummering Hva har de to metodene felles? en if-test deler metoden i to utfall: et basistilfelle med enkel løsning n=1 s.length()==1 et mer komplisert tilfelle hvor parameteren er «en nærmere» basistilfellet kaller påf(n 1) kaller på skriv(s) (s ett tegn kortere) vi antar at metoden virker som den skal når vi bruker (kaller) den.

Finne maksimal verdi i en array Nå prøver vi bevisst å tenke rekursivt før vi starter å lage skisse av programmet. Programskisse: Anta vi har arrayen int A [] og at i er høyeste indeks i A. Startkallet for arrayen A med lengde n blir finnmax(n-1) 1 int finnmax ( int i ) { 2 if ( i =0) 3 // basistilfelle 4 <returner A[ i ]> 5 else 6 <returner største av A[ i ] 7 og finnmax( i 1)> 8 } Fibonaccitallene Fibonaccitallene er definert ved: F0= 1 Fn= F1= 1 Fn=Fn 1+Fn 2 nårn>1. (1) Vi regner ut noen verdier avf: F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 1 1 2 3 5 8 13 21 Finne maksimal verdi i en array Når vi programmerer ut skissen <største av A[i] og finnmax(i-1)> må vi passe på så vi ikke får mer enn ett rekursivt kall: 1... 2 if (A[ i ] > finnmax( i 1)){ 3 return A[ i ] 4 } 5 else { 6 return finnmax( i 1) 7 } 8.... Fibonaccitallene Dette kan implementeres rekursivt slik: 1 2 3 int fib ( int n) { 4 if (n <= 1) { 5 return 1; 6 } else { 7 return fib (n 1) + fib (n 2); 8 } 9 } (Hva skjer hvis vi kaller på fib(-1)?)

4. rekursjonsregel Ikke løs samme instans av et problem i separate rekursive kall F6 F5 F4 F4 F3 F3 F2 F3 F2 F2 F1 F2 F1 F1 F0 F2 F1 F1 F0 F1 F0 F1 F0 F1 F0 Ideen er å lage en metode fargelegg som tar et felt som parameter og som fargelegger feltet og kaller seg selv med hvert nabofelt som parameter (for-løkke) Siden alle felter er 4-nabo med minst to andre felt, skulle vi på denne måten komme til alle felt. Basistilfellet i denne algoritmen er når parameteren er et felt som ikke har umalte naboer. Da blir det heller ingen rekursive kall, men feltet blir fargelagt. La oss for eksemplets skyld ta et kvadratisk rom, hvor feltene også er kvadratiske. Dette kan f.eks. være et rom med kvadratiske fliser. Her et eksempel med 9 9 felt: Dette problemet er rekursivt, fordi det å fargelegge hele rommet kan deles opp i deloppgaver å fargelegge feltene. Det rekursive kallet er nærmere et basistilfelle fordi vi fargelegger eget felt før rekursive kall: antall felt totalt er endelig det gjenstår ett felt mindre å fargelegge enn i den metodeinstansen vi nå er 1. Fargelegg felt 2. Se på alle nabofelter: Hvis feltet ikke er fargelagt, fargelegg det.

Programskisse, der vi tenker oss en datastruktur hvor feltene er objekter av klassen Felt (datastrukturen kan f.eks. være en en array A[][]. 1 void fargelegg ( Felt f ) { 2 f.mal( sinober ) ; // fargelegging 3 nf = f.nestenabo ( ) ; 4 while ( ( nf!= null ) && (! nf.malt ( ) ) { 5 fargelegg ( nf ) ; 6 } 7 } Vi har antatt at Felt har en metode mal(string farge) som fargelegger et Felt-objekt (merker det malt) og en boolsk metode malt() som returnerer true hvis feltet er fargelagt. Oppsummering - programskisse for traversering av en graf (dybde først) behandle dette objektet (f.eks. endre en lokal verdi) For nabo i naboliste: Hvis naboobjekt er ubehandlet og lovlig: Traverser med utgangspunkt i naboobjekt. Algoritmen for å fargelegge ruter i et rektangel: 1 2 void fargelegg ( Felt f ) { 3 f.mal( sinober ) ; // fargelegging 4 nf = f.nestenabo ( ) ; 5 while ( ( nf!= null ) && (! nf.malt ( ) ) { 6 fargelegg ( nf ) ; 7 } kan benyttes generelt på objekter i en graf såfremt: man fra et objekt kan nå alle gjennom nabopekere nestenabo() gir alle naboer til et objekt Rekursive metoder En rekursiv metode er en metode som kaller seg selv. Huskeregler: Det må alltid finnes et basistilfelle som kan løses uten rekursjon. De rekursive kallene må gå i retning av et basistilfelle. Designregel: Anta at de rekursive kallene fungerer. Ikke løs samme instans av et problem i separate rekursive kall