Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

der Universität Oldenburg

Ähnliche Präsentationen


Präsentation zum Thema: "der Universität Oldenburg"—  Präsentation transkript:

1 der Universität Oldenburg
Programmierkurs Java Vorlesung am FB Informatik der Universität Oldenburg Vorlesung 7 Dietrich Boles

2 Gliederung von Vorlesung 7
Speicherverwaltung Stack „Zeiger“ Heap Inkarnationen von Funktionen von Variablen Rekursion Definitionen rekursive Prozeduren rekursive Funktionen Endlosrekursion Backtracking Beispielprogramme

3 Speicherverwaltung Programm- speicher Programmcode Statische Daten
globale Variablen Stack lokale Variablen Daten unter Programmkontrolle Heap

4 Verwaltung durch Laufzeitsystem
Stack Verwaltung durch Laufzeitsystem Arbeitet nach dem Prinzip „last-in-first-out“ Verwaltung von Funktionsaktivierungen Speicherbereich für lokale Variablen p(); return; void p(): int a char b void main(): void main(): void main(): int a float b int a float b int a float b Stack Stack Stack

5 Programmkontrollierte Verwaltung
Heap Programmkontrollierte Verwaltung Speicherzuweisung per Anweisung (new/delete) Zugriff über „Zeiger-Variablen“ (Referenz-Variablen) Unterstützung durch Laufzeitsystem (Garbage Collection, ...) int a int a new int (a); delete (b); char b char b Heap Heap

6 Zeiger Gibt es in Java so nicht, aber Grundlage für Objektrepräsentation Datentyp ADDRESS ADDRESS-Variablen: Speicherung von Speicheradressen Stack oder Heap Stack oder Heap ADDRESS v 2 Heap Heap 1 1 2 double v 3 2 3 4 5 4 5

7 Zeiger ADDRESS(double) v, w; // Anlegen zweier ADDRESS // Variablen auf dem Stack v = new double(); // Speicherplatzzuweisung (Heap) w = new double(); // v und w enthalten als Werte // Speicheradressen *v = ; // Zuweisung eines Wertes an die // Speicheradresse, auf die v zeigt *w = *v ; // dito für w (Dereferenzierung) v = w // v und w zeigen nun auf denselben // Speicherplatz delete v; // Speicherplatzfreigabe delete w;

8 Funktionsinkarnationen
beim Aufruf einer Funktion f ensteht eine Inkarnation von f zur Inkarnation einer Funktion gehören: ein Ausführungspunkt Speicherplätze für funktionslokale Variablen eine Inkarnation wird vernichtet, wenn die Funktion verlassen wird Blockanweisungen entsprechen namenlosen Funktionen, entsprechend gilt der Inkarnationsbegriff auch hier Variableninkarnationen wird während der Programmausführung die Definitionsanweisung einer Variablen v erreicht, entsteht eine Inkarnation (Instanz) von v die Inkarnation von v wird vernichtet, sobald die Lebensdauer von v beendet ist

9 Aktionen beim Aufruf einer Funktion
Inkarnation Aktionen beim Aufruf einer Funktion es wird auf dem Stack ein Aktivierungssegment (Speicherstück) angelegt der aktuelle Zustand des Programms (Registerinhalte) wird im Aktivierungssegment gespeichert im Aktivierungssegment werden Speicherbereiche für Parameter, lokale Variable und temporäre Daten reserviert Aktionen beim Verlassen einer Funktion mit Hilfe der abgespeicherten Registerinhalte kann der Zustand des Programms von vor dem Funktionsaufruf wiederhergestellt werden der Funktionswert wird an geeigneter Stelle abgelegt das Aktivierungssegment wird zerstört

10 Inkarnation Schema: main(): f1(): f2(int j): int i; int i; float x;
int j; return; f2(5+j); Stack j x j f2 f2 x i i i i f1 f1 f1 j f1 j main i main i main i main i main i

11 Rekursion „Definition eines Problems, einer Funktion oder eines Verfahrens durch sich selbst“ bereits bekannt: direkt rekursive Syntaxdiagramme: indirekt rekursive Syntaxdiagramme: Mathematik: <boolescher Ausdruck> :: „true“ | „false“ | „(“ <boolscher Ausdruck> „)“ ; <Anweisung> ::= ... | <while-Anweisung> ; <while-Anweisung> ::= „while“ „(“ <bA> „)“ <Anweisung> ; { n! = falls n = 0 n * (n-1)! sonst

12 Rekursive Prozeduren und Funktionen
Definition (Rekursion): Eine Funktion heißt rekursiv, wenn mindestens zwei Inkarnationen dieser Funktion zur gleichen Zeit bestehen können. Definition (direkte Rekursion): Eine Funktion heißt direkt rekursiv, wenn sich die Funktion selbst aufruft, d.h. wenn die zweite Inkarnation der Funktion durch die Funktion selbst erzeugt wird. Definition (indirekte Rekursion): Eine Funktion heißt indirekt rekursiv, wenn die zweite Inkarnation der Funktion nicht durch die Funktion selbst erzeugt wird. Definition (Rekursionstiefe): Anzahl der Inkarnationen einer Funktion minus 1

13 Rekursive Prozeduren Der Hamster soll bis zur nächsten Wand laufen!
Iterative Lösung: Direkt rekursive Lösung: void zurMauer() { while (vornFrei()) vor(); } void zurMauerR() { if (vornFrei()) { vor(); zurMauerR(); }

14 Rekursive Prozeduren Der Hamster soll alle Körner auf dem aktuellen Feld einsammeln! Iterative Lösung: Direkt rekursive Lösung: void sammle() { while (kornDa()) nimm(); } void sammleR() { if (kornDa()) { nimm(); sammleR(); }

15 Rekursive Prozeduren Korrelation zwischen iterativen und rekursiven Prozeduren: void p() { while ( <Bedingung> ) <Anweisung> } void p1() { if ( <Bedingung> ) { <Anweisung> while ( <Bedingung> ) } void p2() { if ( <Bedingung> ) { <Anweisung> while ( <Bedingung> ) } } } void pR() { if ( <Bedingung> ) { <Anweisung> pR(); }

16 Rekursive Prozeduren Der Hamster soll bis zur nächsten Wand und dann zurück zur Ausgangsposition laufen! Iterative Lösung: void hinUndZurueck() { int anzahl = 0; while (vornFrei()) { vor(); anzahl++; } linksUm(); linksUm(); while (anzahl > 0) { anzahl--;

17 Rekursive Prozeduren Der Hamster soll bis zur nächsten Wand und dann zurück zur Ausgangsposition laufen! Direkt rekursive Lösung: void hinUndZurueckR() { if (vornFrei()) { vor(); hinUndZurueckR(); } else { kehrt(); } void kehrt() { linksUm();

18 Rekursive Prozeduren Schema: main: hUZR (1.) hUZR (2.) hUZR (3.)
hUZR(); vornFrei -> t vor(); hUZR(); -----> vornFrei -> t hUZR(); -----> vornFrei -> f kehrt(); <----- Befehlsfolge: vor(); vor(); kehrt(); vor(); vor();

19 Rekursive Prozeduren Der Hamster soll bis zur nächsten Wand und dann zurück zur Ausgangsposition laufen! Indirekt rekursive Lösung: void hinUndZurueckR() { if (vornFrei()) { laufe(); } else { linksUm(); linksUm(); } void laufe() { vor(); hinUndZurueckR();

20 Rekursive Funktionen Der Hamster soll die Anzahl an Schritten bis zur nächsten Mauer zählen! Iterative Lösung: Rekursive Lösung: int anzahlSchritte() { int anzahl = 0; while (vornFrei()) { vor(); anzahl++; } return anzahl; int anzahlSchritteR() { if (vornFrei()) { vor(); return anzahlSchritteR() + 1; } else return 0; }

21 Rekursive Funktionen Schema: main: aSR (1.) aSR (2.) aSR (3.)
i=aSR(); vornFrei -> t vor(); aSR() > vornFrei -> t aSR() > vornFrei -> f return 0; <----- return 0 + 1; 1 return 1 + 1; 2 i=2;

22 Rekursive Funktionen mit lokalen Variablen
Der Hamster soll die Anzahl an Körnern im Maul zählen! int anzahlKoernerR() { if (!maulLeer()) { gib(); int anz = anzahlKoernerR(); nimm(); // Vermeidung von Seiteneffekten! return anz + 1; } else return 0; } Stack aKR anz aKR anz aKR anz ... aKR anz aKR anz aKR anz main main main main

23 Rekursive Funktionen mit Parametern
Der Hamster soll „anz“-Schritte nach vorne gehen! void vorR(int anz) { if ((anz > 0) && vornFrei()) { vor(); vorR(anz-1); } Stack vorR anz=0 vorR anz=1 vorR anz=1 ... vorR anz=2 vorR anz=2 vorR anz=2 main main main main

24 Rekursive Funktionen / Endlosrekursion
Rekursionstiefe: im Prinzip „unendlich“! erzeugt im allgemeinen einen Laufzeitfehler: Stack overflow! Dem Java-Interpreter kann man die gewünschte Stackgröße mitteilen! void sammleR() { if (kornDa()) { sammleR(); nimm(); }

25 Rekursive Prozeduren und Funktionen
Anmerkungen: zu jedem rekursiv formulierten Algorithmus gibt es einen äquivalenten iterativen Algorithmus Vorteile rekursiver Algorithmen: kürzere Formulierung leichter verständliche Lösung Einsparung von Variablen teilweise sehr effiziente Problemlösungen (z.B. Quicksort) Nachteile rekursiver Algorithmen: weniger effizientes Laufzeitverhalten (Overhead beim Funktionsaufruf) Verständnisprobleme bei Programmiernanfängern Konstruktion rekursiver Algorithmen „gewöhnungsbedürftig“

26 Backtracking-Verfahren
Prinzip: Versuch, eine Teillösung eines gegebenen Problems systematisch zu einer Gesamtlösung auszubauen falls in einer gewissen Situation ein weiterer Ausbau einer vorliegenden Teillösung nicht mehr möglich ist („Sackgasse“), werden eine oder mehrere der letzten Teilschritte rückgängig gemacht die dann erhaltene reduzierte Teillösung versucht man auf einem anderen Weg wieder auszubauen Wiederholung des Verfahrens, bis Lösung gefunden wird oder man erkennt, daß keine Lösung existiert Grundlage der Programmiersprache PROLOG! Bekannte Probleme: Springerproblem Acht-Damenproblem Labyrinthsuche

27 Backtracking-Verfahren
Aufgabe: Der Hamster steht am Eingang eines zyklenfreien Labyrinths, in dem er ein Korn finden und auf dem schnellsten Weg zurücktransportieren soll!

28 Backtracking-Verfahren
boolean gefunden = false; void main() { sucheGeradeAb(); } void sucheGeradeAb() { if (kornDa()) { gefunden = true; nimm(); } if (!gefunden && linksFrei()) { linksUm(); vor(); sucheGeradeAb(); vor(); linksUm(); } if (!gefunden && rechtsFrei()) { rechtsUm(); vor(); sucheGeradeAb(); vor(); rechtsUm(); if (!gefunden && vornFrei()) { vor(); sucheGeradeAb(); vor(); } else { kehrt(); } }

29 { Beispielprogramm 1 Berechnung der Fakultätsfunktion:
n! = falls n = 0 n * (n-1)! sonst public static int fakultaet(int n) { if (n <= 0) return 1; else return n * fakultaet(n-1); } fak(3) = 3 * fak(2) 2 * fak(1) 1 * fak(0) 1 1 * 1 2 * 1 3 * 2 6

30 { Beispielprogramm 2 Berechnung einer Fibonacci-Zahl: 1 falls n = 1
fib(n) = falls n = 2 fib(n-1) + fib(n-2) sonst public static int fib(int n) { if (n <= 2) return 1; else return fib(n-1) + fib(n-2); }

31 { Beispielprogramm 3 McCarthy-Funktion:
es gilt übrigens: mc(n) = 91 für 1 <= n <= 101 { n falls n > 100 mc(n) = mc(mc(n+11)) sonst public static int mc(int n) { if (n > 100) return n - 10; else return mc(mc(n+11)); }

32 { Beispielprogramm 4 Ackermann-Funktion: wächst sehr stark:
ack(4,2) besitzt Stellen ack(4,4) ist größer als 10 hoch 10 hoch 10 hoch 19000 { m falls n = 0 ack(n,m) = ack(n-1,1) falls m = 0 ack(n-1,ack(n,m-1)) sonst public static int ack(int n, int m) { if (n == 0) return m+1; else if (m == 0) return ack(n-1, 1); else return ack(n-1, ack(n,m-1)); }

33 Beispielprogramm 5 Türme von Hanoi: Gegeben: 3 Pfosten mit n Scheiben
Ziel: Lege alle n Scheiben von 1 nach 3 Restriktion 1: immer nur eine Scheibe bewegen Restriktion 2: niemals größere auf kleinere Scheibe 1 2 3 public class Hanoi { public static void main(String[] args) { int hoehe = Terminal.readInt(); verlegeTurm(hoehe, 1, 3, 2); } public static void verlegeTurm(int hoehe, int von, int nach, int ueber) { if (hoehe > 0) { verlegeTurm(hoehe-1, von, ueber, nach); Terminal.out.println(von + “-“ + nach); verlegeTurm(hoehe-1, ueber, nach, von); } } }


Herunterladen ppt "der Universität Oldenburg"

Ähnliche Präsentationen


Google-Anzeigen