Rekursion og dynamisk programmering

Relaterede dokumenter
Dynamisk programmering

Dynamisk programmering

28 Algoritmedesign. Noter. PS1 -- Algoritmedesign

Dynamisk programmering

Rekursion C#-version

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 10

Skriftlig eksamen i Datalogi

Divide-and-Conquer algoritmer

Syntaks og syntaksgenkendelse, særligt regulære udtryk og tilstandsmaskiner og lidt om anvendelser i bioinformatik

Divide-and-Conquer algoritmer

Træer. Datastrukturer & Algoritmer, Datalogi C Forelæsning 9/

Søgetræer: Generel repræsentation af (sorterede) mængder og funktioner Databasesystemer...

Algorithms and Architectures I Rasmus Løvenstein Olsen (RLO) Mm2: Rekursive algoritmer og rekurrens - October 12, 2010

Datalogi C + Datastrukturer og Algoritmer

DM502. Peter Schneider-Kamp

Divide-and-Conquer algoritmer

DANMARKS TEKNISKE UNIVERSITET

Programmering 1999 KVL Side 5-4. Klassen Time: metoder. Metoder i objektet giver mulighed for at ændre tilstanden, eller kigge på tilstanden.

Algorithms and Architectures I Rasmus Løvenstein Olsen (RLO), Jimmy Jessen Nielsen (JJE) Mm2: Rekursive algoritmer og rekurrens - October 10, 2008

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 4

Martin Olsen. DM507 Projekt Del I. 19. marts 2012 FOTO: Colourbox

Løsning af skyline-problemet

Det er muligt at chekce følgende opg. i CodeJudge: og

Divide-and-Conquer algoritmer

Vejledende løsninger

Stakke, køer og lidt om hægtede lister - kapitel 16 og 17

Algorithms & Architectures I 2. lektion

Stakke, køer og lidt om hægtede lister

Forelæsning Uge 4 Mandag

Algoritmer og invarianter

Hashing og hashtabeller

Skriftlig eksamen i Datalogi

Datalogi OB, Efterår 2002 OH er, forelæsning 3/ forstå datastrukturer og algoritmer (teoretisk forståelse og intuition)

Algoritmeanalyse. Øvre grænse for algoritme. Øvre grænse for problem. Nedre grænse for problem. Identificer essentiel(le) operation(er)

Rolf Fagerberg. Forår 2013

AAU, Programmering i Java Intern skriftlig prøve 18. maj 2007

Intervalsøgning. Algoritmisk geometri. Motivation for intervaltræer. Intervalsøgning. Lad der være givet en database over ansatte i en virksomhed

Algoritmisk geometri

Parallelle algoritmer

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 2

Design by Contract Bertrand Meyer Design and Programming by Contract. Oversigt. Prædikater

Rolf Fagerberg. Forår 2012

Forelæsning Uge 3 Torsdag

BRP Kursusintroduktion og Java-oversigt

Om binære søgetræer i Java

Skriftlig eksamen i Datalogi

Hashing og hashtabeller

Sortering. Her: sortering af arrays af objekter

Prioritetskøer ved»heap«, simulering

Virkefeltsregler i Java

DM507 Algoritmer og datastrukturer

Hanne Niels Edith Harald Carsten Jørgen Henrik.

BRP Sortering og søgning. Hægtede lister

DM01 DM Obl. Afl. Jacob Christiansen, , D12, Elias 18/ Side 1 af 11

Sortering af information er en fundamental og central opgave.

Løsning af møntproblemet

Sortering. Eksempel: De n tal i sorteret orden

Binære søgetræer. Binære søgetræer. Nærmeste naboer. Nærmeste nabo

Skriftlig Eksamen DM507 Algoritmer og Datastrukturer

14 Algoritmeanalyse. Noter. Algoritmebegrebet. Hvad er algoritmeanalyse? Problemstørrelse og køretid. Køretid for forskellige kontrolstrukturer.

Søgning og Sortering. Philip Bille

Søgning og Sortering. Søgning Linæer søgning Binær søgning Sortering Indsættelsessortering Flettesortering. Philip Bille

Sortering. Eksempel: De n tal i sorteret orden

Anvendelse af metoder - Programmering

Anvendelse af del og hersk princippet involverer altså problemopdelning og løsningskombination.

Grundlæggende Algoritmer og Datastrukturer

Danmarks Tekniske Universitet

A Profile for Safety Critical Java

Forelæsning Uge 5 Mandag

Danmarks Tekniske Universitet

Ugeseddel 4 1. marts - 8. marts

Søgning og Sortering. Søgning og Sortering. Søgning. Linæer søgning

Binære søgetræer. Binære søgetræer. Nærmeste naboer. Nærmeste nabo

Algoritmer og datastrukturer Course No Cheat Sheet May 15, 2012

Sekvensafstand DM34 - Eksamensopgave. Jacob Aae Mikkelsen

Sortering af information er en fundamental og central opgave.

Sortering. De n tal i sorteret orden. Eksempel: Kommentarer:

Introduktion. Algoritmer og datastrukturer Toppunkter Algoritme 1 Algoritme 2 Algoritme 3. Philip Bille

Danmarks Tekniske Universitet

Forelæsning Uge 3 Torsdag

Introduktion. Introduktion. Algoritmer og datastrukturer. Eksempel: Maksimalt tal

Datalogi OB, Efterår 2002 OH er, forelæsning 10/ Klasser og nedarvning

Danmarks Tekniske Universitet

Danmarks Tekniske Universitet

Forelæsning Uge 3 Torsdag

University of Southern Denmark Syddansk Universitet. DM503 Forelæsning 11

Singleton pattern i C#

Kursus navn: Indledende programmering Kursus nr

Algoritmer og Datastrukturer 1. Gerth Stølting Brodal Aarhus Universitet

22 Hobe. Noter. PS1 -- Hobe. Binære hobe. Minimum-hob og maximum-hob. Den abstrakte datatype minimum-hob. Opbygning af hobe. Operationen siv-ned.

Forelæsning 17, tirsdag 2. november 1999 Søgning efter en given værdi i en tabel. Programmering 1999

DM507 Algoritmer og datastrukturer

Tree klassen fra sidste forelæsning

Danmarks Tekniske Universitet

Abstrakte datatyper C#-version

Opgaver. Oktober 2009

Danmarks Tekniske Universitet

Algoritmer og Datastrukturer 1. Gerth Stølting Brodal

Sekvenser af længde mellem 1 og 4 ord repræsenteres ved en klasse Segment, som uden grundlæggende ser således ud:

Databaseadgang fra Java

Transkript:

Rekursion og dynamisk programmering Datastrukturer & Algoritmer, Dat C Forelæsning 12/10-2004 Henning Christiansen Rekursion: at en procedure kalder sig selv eller et antal metoder kalder hinanden gensidigt. Meget elegant til ting, som er rekursive af natur! Eksempel: Binær søgning private static int binarysearch( Comparable [ ] a, Comparable x, int low, int high ) { if( low > high ) return -1 int mid = ( low + high ) / 2; if( a[ mid ].compareto( x ) < 0 ) return binarysearch( a, x, mid + 1, high ); else if( a[ mid ].compareto( x ) > 0 ) return binarysearch( a, x, low, mid - 1 ); else return mid;} Tidsforbrug: log n. Implementation ved stak (tager compileren sig af) Optimeringer ved bl.a. halerekursion (compiler producerer samme kode som var det skrevet med for eller while ). Dvs. for binær søgning som overfor kan rekursionsstakken helt undgås

Eksempler hvor rekursion er elegant rekursivt definerede datastrukturer, f.eks. et træ (eksempel om et øjeblik) compilere og sprog <sætning> ::= if( <betingelse> ) <sætning> ; while( <betingelse> ) <sætning> ;... Datastrukturen er syntakstræer; Parser, evt. hele compiler (Pascal, men ikke Java) er en samling rekursive procedurer, én for hver syntaktisk kategori. matematiske definitioner ofte rekursive

Træer: rekursiv datastruktur og tilhørende rekursive algoritmer anvendelser: søgetræer, syntakstræer,... Eksempel: Simple træer med tal public class TreesWithNumbers { private TreesWithNumbers left; private TreesWithNumbers right; private int value; public TreesWithNumbers(int n) {value = n;}; public TreesWithNumbers(TreesWithNumbers left, int n, TreesWithNumbers right) {this.left=left; value=n; this.right=right;};... public static void main( String [ ] args ) } { TreesWithNumbers t = new TreesWithNumbers( new TreesWithNumbers(5), 10, new TreesWithNumbers( new TreesWithNumbers(8), 6, new TreesWithNumbers(17) ) ); System.out.println("Træet " + t + " har sum " + t.sum()); t.pp(); }

Rekursive metoder til rekursive strukturer. Det er fristende at skrive public String tostring() {return "(" + left.tostring() + "[" + value + "]" + right.tostring() + ")";}; Denne her er bedre: public String tostring() {return "(" + (left==null? "" : left.tostring()) + "[" + value + "]" + (right==null? "" : right.tostring()) + ")";}; (([5])[10](([8])[6]([17])))

At summe værdierne sammen: Det er fristende at skrive public int sum() {return left.sum() + value + right.sum();}; Denne her er bedre public int sum() {return (left==null? 0 : left.sum()) + value + (right==null? 0 : right.sum());};

Matematiske definitioner, f.eks. n! = 1 x 2 x... x (n-1) x n public class Factorial { public static long factorial( int n ) {if( n <= 1 ) return 1; else return n * factorial( n - 1 ); } public static void main( String [ ] args ) {for( int i = 1; i <= 10; i++ ) System.out.println( factorial( i ) );}}

Eksempel: Fibonacci-tal 0, 1, 1, 2, 3, 5, 8, 13,... hvad er systemet? public static int fib1(int n) {if(n<=1) return n; else return fib1(n-1) + fib1(n-2);} Elegant, smukt, ubrugeligt... eksempel på del-og-hersk når det ikke virker... vi vender tilbage til eksemplet! Iøvrigt: Hvem var Fibonacci: Italiensk forfatter, filosof, rejsende (??) Leonardo Pisano (ca. 1170 1250) Billede lånt på http://www-history.mcs.st-andrews.ac.uk/history/pictdisplay/fibonacci.html

En programmeringsteknik: Del og hersk Generelt mønster: public static Løsning løs(problem p) { if(simpel(p)) return løsningen-på-det-simple-problem; split p op i p1,..., pn; L1 = løs p1; L2 = løs p2;... Ln = løs pn; return kombiner(l1, L2,..., Ln); } Det bedste eksempel: Binær søgning: private static int binarysearch( Comparable [ ] a, Comparable x, int low, int high ) { if( low > high ) return -1; int mid = ( low + high ) / 2; } if( a[ mid ].compareto( x ) < 0 ) return binarysearch( a, x, mid + 1, high ); else if( a[ mid ].compareto( x ) > 0 ) return binarysearch( a, x, low, mid - 1 ); else return mid; Opsplitning af problem i ét delproblem som er halvt så stort. Omkostning for at»kombinere«: konstant. Tidsforbrug: log n. Andre eksempler: Sortering, f.eks. mergesort

Generel formel til vurdering af tidsforbrug public static Løsning løs(problem p) { if(simpel(p)) return løsningen-på-det-simple-problem; split p op i p1,..., pa; L1 = løs p1; L2 = løs p2;... LA = løs pa; return kombiner(l1, L2,..., LA); } Parametre: A, antallet af delproblemer B, mål for relativ størrelse af delproblem (f.eks. B=2 for halvering) k, bestemt ved overhead Theta(N k ) (= prisen for at splitte+kombinere ) T(N) = { O(N log B A ) hvis A > B k { O(N k log N) for A= B k { O(N k ) for A < B k Anvende den på binær søgning...

Del-og-hersk-version af maksimum-sum-problemet /** * Recursive maximum contiguous subsequence sum algorithm. * Finds maximum sum in subarray spanning a[left..right]. * Does not attempt to maintain actual best sequence. */ private static int maxsumrec(int []a,int left, int right) { int maxleftbordersum = 0, maxrightbordersum = 0; int leftbordersum = 0, rightbordersum = 0; int center = ( left + right ) / 2; if( left == right ) // Base case return a[ left ] > 0? a[ left ] : 0; int maxleftsum = maxsumrec( a, left, center ); int maxrightsum = maxsumrec( a, center + 1, right ); for( int i = center; i >= left; i-- ) { leftbordersum += a[ i ]; if( leftbordersum > maxleftbordersum ) maxleftbordersum = leftbordersum; } for( int i = center + 1; i <= right; i++ ) { rightbordersum += a[ i ]; if( rightbordersum > maxrightbordersum ) maxrightbordersum = rightbordersum; } } return max3( maxleftsum, maxrightsum, maxleftbordersum + maxrightbordersum ); Princippet: Her? eller her? eller her??

Træ over rekursive kald for n=8 Uformel analyse: Hvert lag: De to indre løkker skal tilsammen trille alle (= n) elementer igennem. Det er log n lag, dvs. ialt: n log n Ved brug af formel: A: Antal delproblemer = 2. B: Delproblemernes relative størrelse, halvering, dvs. B = 2 k:»overhead«= n; n k = n, dvs, k = 1 Formlens 2. tilfælde: A=B k, 2=2 1 Dvs. O(n k log n) = O(n 1 log n) = O(n log n)

Dynamisk programmering Princippet: Vi skal løse et problem P(n) Hvis vi, for at løse P(n) får brug for, direkte eller indirekte, at kende løsningen på P(1), P(2),..., P(n-1), så beregner vi dem alle fra en ende af og lægger dem i et array. Eksempel: Fibonacci ved dynamisk programmering public static int fib2(int n) //assume n>=2 { int [] fibs = new int [n+1]; fibs[0] = 0; fibs[1] = 1; for(int i=2; i<= n; i++) fibs[i] = fibs[i-1]+fibs[i-2]; return fibs[n];} 0 1 0 1 2 0 1 2 3 0 1 2 3 5 0 1 2 3 5 8 0 1 2 3 5 8 13 0 1 2 3 5 8 13 21 0 1 2 3 5 8 13 21 34

Eksempel, at give byttepenge public final class MakeChange { public static void makechange( int [ ] coins, int differentcoins, int amount, int [ ] coinsused ) { coinsused[ 0 ] = 0; for( int count = 1; count <= amount; count++ ) { int mincoins = count; for( int j = 0; j < differentcoins; j++ ) { if( coins[ j ] > count ) // Cannot use coin j continue; if( coinsused[ count - coins[ j ] ] + 1 < mincoins ) mincoins = coinsused[ count - coins[ j ] ] + 1; }; coinsused[ count ] = mincoins;}} public static void main( String [ ] args ) { // The coins and the total amount of change int numcoins = 5; int [ ] coins = { 1, 5, 10, 21, 25 }; // required: a 1-coin int change = 117; int [ ] used = new int[ change + 1 ]; makechange( coins, numcoins, change, used ); System.out.println( "Best is " + used[ change ] + " coins" );}} NB: Variabelnavne ændret og overflødigt argument (lastcoin) fjernet i forhold til bogen.

Afsluttende øvelse: 4 måder at beregne Fibonacci-tal på: // "Divide & conquer" - not recommended public static int fib1(int n) {if(n<=1) return n; else return fib1(n-1) + fib1(n-2);}

// "Dynamic programming" public static int fib2(int n) //assume n>=2 { int [] fibs = new int [n+1]; fibs[0] = 0; fibs[1] = 1; for(int i=2; i<= n; i++) fibs[i] = fibs[i-1]+fibs[i-2]; return fibs[n];}

// "Memoization" private static HashMap table = new HashMap(); public static int fib3(int n) { Object resultcell; if((resultcell = table.get(new Integer(n)))!= null ) return ((Integer)resultCell).intValue(); else {int result; if(n<=1) result=n; else result=fib3(n-1) + fib3(n-2); table.put(new Integer(n), new Integer(result)); return(result);};}

// "Direct algorithm" // - can be seen as optimized DynProg or memo //... however in the long run outperformed by Memo! public static int fib4(int n)//assume n>=2 {int f0=0; int f1=1; int buf; for(int i=2;i<=n;i++) f1= f0+(f0=f1); return f1;};

Afslutning: Rekursion er elegant for de rigtige problemer Del-og-hersk er en måde at forstå mange rekursive algoritmer på, f.eks. søgning og sortering Dynamisk programmering er en lignende, ikke rekursiv teknik, som er god når et problem splittes op i lignende, men mindre delproblemer og specielt når samme delproblem kan optræde flere gange. Memoisering er kan ses som dyn.prog. med langtidshukommelse, og som kun beregner det, der er brug for. kræver en tungere datastruktur, men tjener sig ind i længden