Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 1 Algorithmen und Datenstrukturen Übungsmodul 8 Dr. W. Narzt u. Dr. A. Stritzinger.

Ähnliche Präsentationen


Präsentation zum Thema: "Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 1 Algorithmen und Datenstrukturen Übungsmodul 8 Dr. W. Narzt u. Dr. A. Stritzinger."—  Präsentation transkript:

1 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 1 Algorithmen und Datenstrukturen Übungsmodul 8 Dr. W. Narzt u. Dr. A. Stritzinger Institut für Wirtschaftsinformatik- Software Engineering JKU Linz

2 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 2 Bäume - Definitionen Definition: nach Wirth [86, S. 200f] Eine Baumstruktur vom Grundtyp T ist entweder die leere Struktur oder ein Knoten vom Typ T mit einer endlichen Zahl verknüpfter, voneinander verschiedener Baumstrukturen vom Grundtyp T, sogenannte Teilbäume (subtrees). Definition n. Sedgewick p. 230 ff Ein Baum ist ein Knoten (Wurzel), der mit einer Folge von disjunkten Bäumen verbunden ist. Eine derartige Folge nennt man Wald (forest). Ein Baum besteht aus Knoten (nodes), die durch Kanten (edges) verbunden sind. In den Knoten sind Nutzdaten (Elemente) gespeichert.

3 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 3 Rekursion - Konzept Rekursion im Allgemeinen bedeutet, dass sich etwas als Teil enthält oder mithilfe von sich selbst definiert ist. Veranschaulichung: Mathematische Definition der Fakultätsfunktion: fak(n) = n* fak(n-1); fak(0) = 1. Rekursive Algorithmen: Wenn eine Funktion, Prozedur oder Methode einen Aufruf von sich selbst enthält (= direkte Rekursion). Wenn eine Methode eine andere aufruft und diese wiederum die erste direkt oder indirekt ruft (= indirekte Rekursion)

4 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 4 Rekursionsbedingungen Ein rekursiver Aufruf darf nicht die gleichen Parameterwerte erhalten, wie die aktuelle Ausführung, da dies zu einer endlos Rekursion führen würde. Statt dessen muss bei jedem rekursiven Aufruf, die durch die Parameter definierte Aufgabe etwas "kleiner" sein. Jeder rekursive Algorithmus muss eine Fallunterscheidung enthalten mit mindestens einem nicht rekursiven Zweig, der bei der Terminierung ausgeführt wird (kann u.U. leer sein). Bei jedem rekursiven Aufruf muss ein neuer Datensatz für alle lokalen Variablen und Parameter angelegt werden, der während der Algorithmusausführung, den darunterliegenden Datensatz verbirgt. Stack-verwaltete (Aktivierungs-) Datensätze sind in fast allen modernen Programmiersprachen üblich. Für praktische Anwendungen muss die Tiefe der Rekursion relativ klein sein.

5 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 5 Beispiel: Fakultät berechnen int factorial( int n) { if (n > 1) { return factorial( n - 1) * n; } else { return 1; } trace: factorial(5), factorial(4), factorial(3), factorial(2), factorial(1) return 1 return 1*2 return 2*3 return 6*4 return 24*5 ergebnis: 120

6 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 6 Rekursion vs. Iteration Die Falkultätsfunktion kann natürlich einfacher und effizienter iterativ berechnet werden int factorial( int n) { int result = 1; for (int i=2; i<=n; i++) { result = result * i; } return result; } Grundsätzlich gilt: Jeder rekursive Algorithmus kann auch iterativ (d.h. mittels Wiederholungs- aktionen) gelöst werden und umgekehrt kann jede iterative Lösung in eine rekursive überführt werden. Rekursive Algorithmen eigenen sich besonders dann, wenn das zugrundeliegende Problem rekursiv definiert ist, oder wenn die Datenstrukturen rekursiv sind.

7 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 7 Beispiel: Fibonacci-Funktion Leonardo Fibonacci (ital. Mathematiker, 12 Jhdt. Pisa) fand eine Reihe, welche angeblich die Populationsentwicklung von Kaninchen präzise beschreibt. Dabei hängt die Zahl der Kaninchen einer Generation n von der Summe der Zahl der Eltern-Generation (n-1) und der Zahl der Großeltern-Generation (n-2) ab. Fibonacci-Reihe: rekursive Fassung: Anzahl der Aufrufe wächst exponentiell, daher ziemlich unbrauchbar! besser: iterative Fassung: int fib( int n) { if (n==0) return 0; if (n==1) return 1; return fib(n-1) + fib(n-2); } int fib( int n) { int i = 1, x = 1, y = 0, z = 0; while (i

8 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 8 Bäume - Begriffe Der Knoten an der Spitze heißt Wurzel des Baumes. Ein Pfad ist eine Liste von zusammenhängenden Kanten. Ausgehend von der Wurzel kann jeder Knoten über genau einen Pfad aus Kanten erreicht werden. Jeder Knoten, außer der Wurzel hat genau einen Vorgänger. Dieser wird auch als Elternknoten, Vater, Mutter (parent) bezeichnet. Die Nachfolgerknoten, die mit einem Vorgänger durch eine Kante verbunden sind bezeichnet man auch als Kindknoten, Sohn oder Tochter (children). Knoten ohne Nachfolger, werden als Bätter (leaves), Knoten mit Nachfolgern als innere Knoten bezeichnet. Die Ebene (Stufe, level) eines Knotens ist um 1 größer als die Ebene des Vorgängers (Wurzel hat Ebene = 0). Die Höhe eines Baumes ist das Maximum der Ebenen aller Knoten. Der Grad eines Baumes gibt die maximal mögliche Anzahl der direkten Nachfolgerknoten eines Knotens an. (Binärbaum: Grad = 2)

9 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 9 Binärbaum und Binärer Suchbaum Binärbaum Ein Binärbaum ist ein Baum, dessen Grad 2 beträgt. l Ein Binärbaum mit N inneren Knoten hat maximal N+1 Blätter. l Ein Binärbaum mit N inneren Knoten hat maximal 2*N Kanten: N-1 zu inneren Knoten N+1 zu Blättern. Binärer Suchbaum (Definition n. Sedgewick p. 531) Ein binärer Suchbaum (binary search tree, BST) ist ein Binärbaum, der mit jedem inneren Knoten ein Schlüsselattribut assoziiert und die Eigenschaft hat, dass für jeden Knoten K gilt: die Schlüsselwerte aller Knoten des linken Unterbaums sind kleiner und die Schlüsselwerte des rechten Unterbaums sind größer oder gleich dem Schlüsselwert des Knotens K.

10 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 10 Binärer Suchbaum in Jana type Tree = { reftype Item = { String key int value } reftype Node = { Item item Node left Node right } Node root init() {root = null}... // Algorithmen } Verwendung: Tree t t.init() t.insert( item) Item i = t.search( key)

11 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 11 void insert( Item x) { root = insertRec(root,x) } Item search( String key) { return searchRec(root,key) } Node insertRec( Node h, Item x) { if (h == null) return new Node(x) if (x^.key < h^.item^.key) h^.left = insertRec(h^.left, x) else h^.right = insertRec(h^.right, x) return h } Item searchRec( Node h, String key) { if (h == null) return null if (key == h^.item^.key) return h^.item if (key < h^.item^.key) return searchRec(h^.left, key) else return searchRec(h^.right, key) } Binärer Suchbaum: Einfügen und Suchen (rekursiv)

12 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 12 Binärer Suchbaum: Einfügen (iterativ) void insertIter(Item x) { if (root == null) root = new Node(x) else { Node parent, current = root while (true) { parent = current if (x^.key < current^.item^.key) { current = current^.left if (current == null) { parent^.left = new Node(x) return; } } else { current = current^.right if (current == null) { parent^.right = new Node(x) return; } } // while } // else }

13 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 13 Binärer Suchbaum: Suchen (iterativ) Item searchIter( String key) { Node current = root while (current != null) { if (current^.item^.key == key) return current^.item if (key < current.item.key) current = current^.left else current = current^.right } return null // not found }

14 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 14 Binärbaum: In-/Pre-/Postorder Traversierung (rekursiv) void inorder() { traverseInorderRec(root) } void traverseInorderRec( Node h) { if (h == null) return traverseInorderRec(h^.left) h^.item^.visit() traverseInorderRec(h^.right) } void traversePreorderRec( Node h) { if (h == null) return h^.item^.visit() traversePreOrderRec(h^.left) traversePreOrderRec(h^.right) } void traversePostorderRec( Node h) { if (h == null) return traversePostOrderRec(h^.left) traversePostOrderRec(h^.right) h^.item^.visit() }

15 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 15 Binärbaum: Preorder Traversierung (iterativ) void traverse() { traverseIter(root); } void traverseIter( Node h) { NodeStack s = new NodeStack s.push(h) while (!s.isEmpty()) { h = s.pop() h^.item^.visit() if (h^.right != null) s.push(h^.right) if (h^.left != null) s.push(h^.left) } //zu beachten: zuerst wird rechter Teilbaum gekellert!

16 Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 16 Binärbaum: Levelorder Traversierung (iterativ) void traverse() { traverseLevels(root) } void traverseLevels( Node h) { NodeQueue q = new NodeQueue q.enqueue(h) while (!q.isEmpty()) { h = q.dequeue() h^.item.^visit() if (h^.left != null) q.enqueue(h^.left) if (h^.right != null) q.enqueue(h^.right) }


Herunterladen ppt "Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 1 Algorithmen und Datenstrukturen Übungsmodul 8 Dr. W. Narzt u. Dr. A. Stritzinger."

Ähnliche Präsentationen


Google-Anzeigen