6 Rekursion. 6.1 Rekursionens fyra principer. 6.2 Några vanliga användningsområden för rekursion. Problem löses genom:



Relevanta dokument
Föreläsning 6: Introduktion av listor

Föreläsning 7. Träd och binära sökträd

Föreläsning 7 Innehåll. Rekursion. Rekursiv problemlösning. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursion. Rekursivt tänkande:

Algoritmanalys. Genomsnittligen behövs n/2 jämförelser vilket är proportionellt mot n, vi säger att vi har en O(n) algoritm.

Föreläsning 13. Rekursion

Tentamen TEN1 HI

Dugga Datastrukturer (DAT036)

Träd, binära träd och sökträd. Koffman & Wolfgang kapitel 6, avsnitt 1 4

Exempel på listor (klassen ArrayList). Ett exempel med fält. Avbildning är en speciell typ av lista HashMap.

Lösningsförslag för tentamen i Datastrukturer (DAT037) från

Sätt att skriva ut binärträd

Tentamen Datastrukturer D DAT 036/DIT960

Föreläsning 6 Innehåll. Rekursion. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursiv problemlösning. Rekursion. Rekursivt tänkande:

Föreläsning 11 Datastrukturer (DAT037)

Föreläsning 4. Kö Implementerad med array Implementerad med länkad lista Djup kontra bredd Bredden först mha kö

2 Modul 2 - (Länkade) Listor

public static void mystery(int n) { if (n > 0){ mystery(n-1); System.out.print(n * 4); mystery(n-1); } }

Tentamen: Programutveckling ht 2015

Tentamen'('Datastrukturer,'algoritmer'och'programkonstruktion.'

Objektorienterad programmering D2

Föreläsning 13 och 14: Binära träd

Föreläsning 9 Innehåll. Söndra och härska. Fibonaccitalen. Söndra och härska. Divide and conquer teknik för att konstruera rekursiva algoritmer.

Textsträngar från/till skärm eller fil

Introduktion till arv

TDIU01 - Programmering i C++, grundkurs

Introduktion till algoritmer - Lektion 4 Matematikgymnasiet, Läsåret Lektion 4

Föreläsning 4 Datastrukturer (DAT037)

Rekursion och induktion för algoritmkonstruktion

Introduktion till algoritmer - Lektion 3 Matematikgymnasiet, Läsåret Lektion 3

Algoritmer och datastrukturer H I HÅKAN S T R Ö M B E R G N I C K L A S B R A N D E F E L T

Objektorienterad programmering E. Back to Basics. En annan version av printtable. Ett enkelt exempel. Föreläsning 10

Lösningsförslag till exempeltenta 1

Datastrukturer och algoritmer

Tommy Färnqvist, IDA, Linköpings universitet

BINÄRA TRÄD. (X = pekarvärdet NULL): struct int_bt_node *pivot, *ny; X X X 12 X X 12 X X -3 X X

Tentamen Datastrukturer (DAT037)

Dekomposition och dynamisk programmering

Föreläsning Datastrukturer (DAT036)

Uppgift 1 ( Betyg 3 uppgift )

Föreläsning 1, vecka 7: Rekursion

Omtentamen (del 1, 6 högskolepoäng) i Programkonstruktion och datastrukturer (1DL201)

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 8 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Föreläsning 9 Innehåll. Söndra och härska. Fibonaccitalen. Söndra och härska. Divide and conquer teknik för att konstruera rekursiva algoritmer.

Föreläsning 10. ADT:er och datastrukturer

Tentamen DE12, IMIT12, SYST12, ITEK11 (även öppen för övriga)

Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6

Tentamen Datastrukturer (DAT036)

Föreläsning 8 Datastrukturer (DAT037)

Lösningsförslag för tentamen i Datastrukturer (DAT036) från

Programmering för Språkteknologer II. Innehåll. Associativa datastrukturer. Associativa datastrukturer. Binär sökning.

Rekursion. Koffman & Wolfgang kapitel 5

Tentamen i Objektorienterad programmering

Föreläsning 4 Datastrukturer (DAT037)

Påminnelse: en datatyp för bilder. Programmering. En datatyp för bilder. Spegelbild. hh.se/db2004

Metodanrop - primitiva typer. Föreläsning 4. Metodanrop - referenstyper. Metodanrop - primitiva typer

Funktionell programmering DD1361

Föreläsning 2 Datastrukturer (DAT037)

Fredag 10 juni 2016 kl 8 12

Sökning och sortering

Rekursion. Att tänka rekursivt Att programmera rekursivt i Java Exempel. Programmeringsmetodik -Java 254

Tentamen i Algoritmer & Datastrukturer i Java

Programmering A. Johan Eliasson

DELPROV 1 I DATAVETENSKAP

Att använda pekare i. C-kod

Tentamen, EDAA20/EDA501 Programmering

Översikt. Stegvis förfining. Stegvis förfining. Dekomposition. Algoritmer. Metod för att skapa ett program från ett analyserat problem

Föreläsning Datastrukturer (DAT036)

Programmering för språkteknologer II, HT2014. Rum

Tentamen Datastrukturer (DAT036)

Tentamen Datastrukturer (DAT036)

SCB :-0. Uno Holmer, Chalmers, höger 2 Ex. Induktiv definition av lista. // Basfall

Programmering för språkteknologer II, HT2014. Rum

maxlist-1. Indexerad lista Länkad lista

Tentamen OOP

Algoritmer, datastrukturer och komplexitet

Skizz till en enkel databas

Tentamen Datastrukturer D DAT 035/INN960

if (n==null) { return null; } else { return new Node(n.data, copy(n.next));

Tentamen, Algoritmer och datastrukturer

SORTERING OCH SÖKNING

Övning 4. Hashning, sortering, prioritetskö, bästaförstsökning. Hitta på en perfekt hashfunktion för atomer. Hur stor blir hashtabellen?

Övningar Dag 2 En första klass

String [] argv. Dagens Agenda. Mer om arrayer. Mer om arrayer forts. String [] argv. argv är variabelnamnet. Arrayer och Strängar fortsättning

TDDI16 Datastrukturer och algoritmer. Algoritmanalys

Quicksort. Koffman & Wolfgang kapitel 8, avsnitt 9

Algoritmer, datastrukturer och komplexitet

Objektorienterad programmering i Java

Föreläsning 4: Kombinatorisk sökning

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Lösningsförslag till exempeltenta 2

Föreläsning 4: Giriga algoritmer. Giriga algoritmer

Föreläsning 7. Träd och binära sökträd

Tentamen Programmeringsteknik II och NV2 (alla varianter) Skriv bara på framsidan av varje papper.

Tentamen Datastrukturer (DAT036)

Stack, specifikation. Stack och Kö. Y s t M A p. Stack. <== > Y s t M A p <== > Prioritetskö

Klassen BST som definierar binära sökträd med tal som nycklar och enda data. Varje nyckel är unik dvs förekommer endast en

Tentamen på kursen DA7351, Programmering , kl Malmö högskola Teknik och samhälle. DA7351, Programmering

Lösningsförslag till tentamen i EDA011/EDA017 Programmeringsteknik för F, E, I, π och N 27 maj 2008

Föreläsning 8 Innehåll

TENTAMEN I DATASTRUKTURER OCH ALGORITMER DVG B kl. 14:00-19:00

Transkript:

6 Rekursion 6.1 Rekursionens fyra principer Problem löses genom: 1. förenkling med hjälp av "sig själv". 2. att varje rekursionssteg löser ett identiskt men mindre problem. 3. att det finns ett speciellt basfall som kan utvärderas direkt. 4. att problemets storlek minskar och slutligen når basfallet genom förenklingen. Detta kan även uttryckas som att en rekursiv lösning: 1. måste ha ett basfall. 2. måste ha (minst) ett rekursionsfall. 3. i varje rekursivt anrop måste närma sig basfallet i diskreta steg. D v s, man måste gå en förbestämd sträcka åt rätt håll varje gång. Det är alltså inte tillåtet (eller möjligt) att närma sig med ett procentuellt steg varje gång. 6.2 Några vanliga användningsområden för rekursion quicksort en sökalgoritm binärsökning en sökalgoritm Operationer på träd en datastruktur. Operationer på grafer en datastruktur.

6.3 Söka i telefonkatalogen 6.3.1 Generell lösning (binärsökning): 1. Slå upp katalogen på mitten 2. Se vilken halva namnet är i 3. Slå upp den halvan på mitten 4. Upprepa 2-4 tills rätt sida hittats Hela katalogen Rätt halva Fel halva F.H. R.H. R.H. F.H. och så vidare

6.3.2 Rekursiv lösning //Pre: 'first' är första indexet och 'last' är sista indexet i // arrayen 'katalog' //Post: result = -1 om numret inte hittades, annars numret som // tilhör personen 'person'. int hittanummer(katalogtype katalog[], int first, int last, string person) if(first > last) // numret finns inte return -1; int mid = (first+last)/2; // mitten på kat. if(person == katalog[mid].namn) //numret finns return katalog[mid].nummer; if(person < katalog[mid].namn) return hittanummer(katalog, first, mid-1, person); return hittanummer(katalog, mid+1, last, person);

6.4 Hitta största talet i en array 6.4.1 Iterativ lösning int storstatalet(int* array, int arraysize) int max = array[0]; for(int i=1; i < arraysize; i++) if(max < array[i]) max = array[i]; return max; 6.4.2 Rekursiv lösning (Tänk speciellt på 'max') int storstatalet(int* array, int i, int max, int arraysize) if(i >= arraysize) return max; if(max < array[arraysize]) max = array[i]; return storstatalet(array, i+1, max, arraysize);

6.5 Utskrift av en sträng baklänges 6.5.1 Iterativ lösning void baklanges(char* ord) int ord_length = strlen(ord); for(int i = ord_length - 1; i >= 0; i--) cout << ord[i]; 6.5.2 Rekursiv lösning void baklanges(char* ord, int ord_length) if(ord_length >= 0) cout << ord[ord_length]; baklanges(ord, ord_length - 1); Anmärkning Ofta innebär rekursiva operationer att man måste ha med en eller flera extra parametrar jämfört med dess iterativa motsvarighet. Man vill generellt undvika att konstruera operationer med långa parameterlistor för användare av operationen eftersom semantiken blir mer komplex. Om en rekursiv operation har parametrar som måste eller bör döljas för användaren kan man enkelt konstruera ytterligare en operation som en gränssnittsoperation med en mindre parameterlista. Gränssnittsoperationen anropar den rekursiva operationen. void baklanges(char* ord) int ord_length = strlen(ord); baklanges(ord, ord_length); Operationen ovan är en gränssnittsoperation till den rekursiva operationen baklanges. Om de två operationerna ingår i en klass skulle gränssnittsoperationen vara publik och den rekursiva operationen skulle vara privat. På så sätt ger man användaren (klienten) ett enklare och tydligare gränssnitt. Dessutom blir kontraktet för gränssnittsoperationen enklare, vilket speglar en enklare och tydligare semantik (innebörd).

6.6 Beräkning av fakulteten 6.6.1 Iterativ lösning int fakultet(int n) int fakulteten = 1; for(int i = 1; i <= n; i++) fakulteten = fakulteten * i; return fakulteten; 6.6.2 Rekursiv lösning int fakultet(int n) if(n==0) return 1; return n * fakultet(n-1); //Basfall //Rekursionsfall

6.7 Rekursiv list size // privat operation, klienter får använda den publika // gränssnittsoperationen nedan. // pre: 'head' pekar på första noden i listam // post: result = antalet element i listan. int List::size(Node*& head) if(head == 0) return 0; return 1 + size(head->next); // Publik gränssnittsoperationen till ovanstående // Pre: true // Post: result = antalet element i listan. int List::size() return size(head); 6.8 Rekursiv list insert // privat operation // Pre: 'list' pekar på första noden i listan. // Post: 'element' insatt i storleksordning i 'list' void List::insert(Node*& list, Element element) Node* newnode; if( (list == 0) (element < list->data) ) newnode = new Node; newnode->data = element; newnode->next = list; list = newnode; insert(list->next, element); Anmärkning Listan antas vara sorterad. Hur kan man skriva en operation som lägger till ett element på en viss position?

6.9 Rekursiv list remove // Pre: 'list' pekar på första noden i listan och 'element' finns i // listan. // Post: Första förekomsten av 'element' finns inte längre i listan void List::remove(Node*& list, Element element) Node* nodetoremove; if(list->data == element) nodetoremove = list; list=list->next; delete nodetoremove; nodetoremove = 0; remove(list->next, element); Anmärkning Denna remove-operation tar bort ett element per värde. Hur kan man skriva en rekursiv remove-operation som tar bort på position? 6.10 Igenkänning av palindrom Ett ord är ett palindrom om det har samma bokstav först och sist och om ordet minus första och sista bokstaven är ett palindrom. En tom sträng är ett palindrom. (Basfall) Ett enda tecken är också ett palindrom. 6.10.1 Pseudokod för palindromigenkänning: bool ispal(ord) om (ord är en tom sträng eller ett enda tecken) return true; annars om (ordets första och sista bokstäver är samma) return ispal(ordet minus första och sista bokstaven) annars return false; slut ispal

6.11 Quicksort Är en vanlig och mycket snabb algoritm för sortering av arrayer och linkande. Algoritmen bygger på att dela upp den stora mängden värden i mindre delar, sortera dessa delar och sedan sätta ihop delarna igen. Man hittar först en pivot och sorterar alla element utifrån denna pivot i två halvor. Quicksort anropas sedan rekursivt med båda halvorna (som inte behöver vara lika stora). Stegen för quicksort är följande: 1. Om det finns något att sortera gör 2,3,4 annars inget. 2. hitta pivot 3. sortera i två halvor (s1 och s2) 4. anropa quicksort med halvorna 5. Sätt in pivoten på rätt ställe (mellan s1 och s2) Exempel - Körning av quicksort 3 2 5 1 1. Inte tom, gör 2,3,4 2. Pivot väljs till 3 (först i mängden) p 3 2 5 1 3. Dela mängden i två halvor efter pivoten 3 2 1 5 värdena i s1 är nu alla mindre än pivoten och s2 större. 4. anropa quicksort med s1 och s2 Första halvan: 2 1 1. Inte tom, gör 2,3,4 2. Hitta pivot 2 (först i mängden) 3. Dela mängden i två halvor efter pivoten p s1 2 1

4. anropa quicksort med halvorna (inget händer) 5. Sätt in pivoten mellan s1 och s2 1 2 Andra halvan: 5 1. Inte tom, gör 2,3,4 2. Hitta pivot 5 (enda elementet) 3. Dela mängden i två halvor efter pivoten (inte mycket att göra) 4. Anropa quicksort med halvorna (inget händer) 5. Sätt in pivoten mellan s1 och s2 (inget händer) Fortsättning på huvudalgoritmen: P s1 s1 s2 3 2 1 5 Delmängderna s1 och s2 är nu sorterade: 3 1 2 5 5. Sätt in pivoten (3) mellan s1 och s2 1 2 3 5 Sorterad och klar. 6.12 Vanliga rekursionsapplikationer Grammatikkonstruktion de flesta språk definieras med hjälp av något pseudospråk (oftast BNF) som är rekursivt. Detta förenklar konstruktionen av parsers, dvs grammtikkontrollen i en kompilator Träd är rekursivt definierade vilket gör att rekursiva operationer på träden är naturliga. Grafer s.o. Länkade listor s.o. Många matematiska problem som kan förenklas till "mindre versioner av sig själva", ex fakultet, exponent Problem som kan lösas med hjälp av matematisk induktion för att bevisa något.