Geordnete Binärbäume Prof. Dr. Martin Wirsing in Zusammenarbeit mit Gilbert Beyer und Christian Kroiß http://www.pst.ifi.lmu.de/lehre/wise-09-10/infoeinf/ WS 09/10
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 2 Geordnete Binärbäume Motivation Eine Datenstruktur für ein Namensverzeichnis soll implementiert werden Die Datenstruktur soll die Operationen find, insert und print anbieten Mit der Zeit wird die Menge an Namen wachsen (>1000) Beispiele Julia 0 1 2 3 4 5 Doris Harry Tom Romeo Doris Julia Tom namen[2] = Julia Julia Romeo 1. Array 2. Liste 3. Geordnete Binärbäume (balanciert und zu einer Liste entartet)
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 3 Geordnete Binärbäume Ein Binärbaum b heißt geordnet, wenn b leer ist oder wenn folgendes für alle nichtleeren Teilbäume t von b gilt: Der Schlüssel von t ist größer (oder gleich) als alle Schlüssel des linken Teilbaums von t und kleiner (oder gleich) als alle Schlüssel des rechten Teilbaums von t > 7 < 5 > > 3 9 10 < 12
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 4 Geordnete Binärbäume Beispiel: Geordnet sind: 7 (abstrakte Darstellung) Der leere Baum und der Baum t: t = 5 8 3 6 12 Nicht geordnet ist der Baum t1: 7 t1 = 5 8 3 9 12
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 5 Suche im geordneten Binärbaum Prinzipieller Ablauf der Berechnung von t.find(6): 1. Vergleiche 6 mit dem Wert der Wurzel; 2. Da 6<7, gehe zum linken Kindknoten; 6<7 7 5 8 3 6 12
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 6 Suche im geordneten Binärbaum Prinzipieller Ablauf der Berechnung von t.find(6): 1. Vergleiche 6 mit dem Wert der Wurzel; 2. Da 6<7, gehe zum linken Kindknoten; 3. Vergleiche 6 mit dem Wert dieses Knotens; 4. Da 6>5, gehe zum rechten Kindknoten dieses Knotens; 3 6<7 5 7 6>5 6 8 12
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 7 Suche im geordneten Binärbaum Prinzipieller Ablauf der Berechnung von t.find(6): 1. Vergleiche 6 mit dem Wert der Wurzel; 2. Da 6<7, gehe zum linken Kindknoten; 3. Vergleiche 6 mit dem Wert dieses Knotens; 4. Da 6>5, gehe zum rechten Kindknoten dieses Knotens; 5. Vergleiche 6 mit dem Wert dieses Knotens; 3 6<7 5 7 6>5 6 8 12 6==6 return true; 6. Da 6==6, gebe Ergebnis true zurück.
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 8 Suche im geordneten Binärbaum (Implementierung) t t.find(6): 1. Suche zunächst in BinTree. 2. Wenn t nicht leer, delegiere die Aufgabe an Node durch Aufruf von anchor.find(6); 3. Verfahre wie auf den vorgehenden Folien. key=5 :BinTree 6<7 6>5 key=7 t.anchor key=10 key=3 key=6 6==6 return true key=12
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 9 public class BinTree {... public boolean find(int key) { if (anchor == null) return false; else return anchor.find(key);... class Node {... boolean find(int key) { Node current = this; while(current.key!= key) // solange nicht gefunden, { if (key < current.key) // gehe nach links? current = current.left; else // sonst gehe nach rechts current = current.right; if(current == null) return false; //nicht gefunden! return true; Suche im geordneten Binärbaum Gibt true zurück, wenn key im Baum; sonst wird false zurückgegeben //gefunden; gib true zurück
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 10 public class BinTree {... public Object findvalue(int key) { if (anchor == null) return null; else return anchor.findvalue(key);... class Node {... boolean findvalue(int key) { Node current = this; while(current.key!= key) // solange nicht gefunden, { if (key < current.key) // gehe nach links? current = current.left; else // sonst gehe nach rechts current = current.right; if(current == null) return null; //nicht gefunden! return current.value; Suche im geordneten Binärbaum Gibt value zurück, wenn key im Baum; sonst wird null zurückgegeben //gefunden; gib true zurück
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 11 Beim Einfügen in einen geordneten Binärbaum wird rekursiv die richtige Stelle gesucht, so dass wieder eine geordneter Binärbaum entsteht. Beispiel: t.insert(8) ergibt: Einfügen in geordneten Binärbaum (Zur Vereinfachung der Darstellung wird hier nur ein Schlüssel und kein Wert eingefügt.) 7 t = t = t.insert(8) 10 5 5 7 10 3 6 12 3 6 8 12
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 12 Einfügen in geordneten Binärbaum (Implementierung) t.insert(8) :BinTree t this... key=5 key=7 key=10 key=3 key=6 key=12 Aufruf von t.insert(id):
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 13 Einfügen in geordneten Binärbaum (Implementierung) t.insert(8) :BinTree t this... key=5 key=7 key=10 key=3 key=6 key=12 Delegieren der Aufgabe durch Aufruf von achor.insert(id):
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 14 Einfügen in geordneten Binärbaum (Implementierung) anchor.insertkey(8): :BinTree t this... this key=5 key=7 key=10 key=3 key=6 key=12 Delegieren Delegieren der Aufgabe der durch Aufgabe durch Aufruf von Aufruf anchor.insertkey(id): von head.add(x): Durchlauf durch das Node-Geflecht mit zwei Hilfsvariablen current und parent
t this parent Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 15 anchor.insert(8):... this current Einfügen in geordneten Binärbaum (Implementierung) key=3 key=5 :BinTree key=6 key=7 Falls id > current.key, gehe nach Setze rechts: if(id > current current.key) = this; current parent = current.right; = current; key=10 key=12 Delegieren der Aufgabe durch Aufruf von anchor.insert(id): Durchlauf durch das Node-Geflecht mit zwei Hilfsvariablen current und parent
this Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 16 anchor.insert(8): current... this current parent Einfügen in geordneten Binärbaum (Implementierung) key=3 key=5 :BinTree key=6 key=7 Und Falls setze: x > current.elem, parent gehe nach = current; rechts: if(x > current.elem) current = current.right; key=10 key=12
this Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 17 anchor.insert(8): current... this current parent Einfügen in geordneten Binärbaum (Implementierung) key=3 key=5 :BinTree key=6 key=7 Und Falls setze: id < current.key, parent gehe nach = links: current; if(key < current.key) current = current.left; key=10 key=12
this Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 18 anchor.insert(8): current... this current null parent Einfügen in geordneten Binärbaum (Implementierung) Wenn current= null, füge neuen Knoten ein: if(current Falls x == < null) current.elem, :BinTree { parent.left gehe nach links: if(x = new < Node(null,id,null); current.elem) current = current.left; return this; key=7 key=5 key=10 key=3 key=6 key=12
this Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 19 anchor.insert(8): current... this current parent Einfügen in geordneten Binärbaum (Implementierung) null key=3 key=5 :BinTree key=6 key=7 Wenn current= null, füge neuen Knoten ein: if(current == null) { parent.left = new Node(null,id,null); return this; key=8 key=10 key=12
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 20 Einfügen in geordneten Binärbaum Fügt einen neuen Knoten mit Schlüssel id an der richtigen Stelle im geordneten Baum ein public void insert(int id, Object o) { if(anchor==null) // falls kein Knoten im anchor anchor = new Node(null, id, o, null,); // neuer Knoten else anchor = anchor.insert(id, o); wobei insert in class Node folgendermaßen definiert wird:
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 21 Node insert(int id, Object o) { Node current = this; // starte bei this Node parent; while(true) // terminiert intern { parent = current; Einfügen in geordneten Binärbaum (Implementierung) if(id < current.key) // gehe nach links? { current = current.left; if(current == null) // am Ende füge links ein { parent.left = new Node(null, id, o, null); return this; // end if go left else { current = current.right; if(current == null) // am Ende füge rechts ein { parent.right = new Node(null, id, o, null); return this; // end else go right // end while Fügt einen neuen Knoten passend ein Achtung:id darf nicht im Baum vorkommen! // falls id > current.key, gehe nach rechts
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 09/10 22 Zusammenfassung Binäre Bäume können in Java implementiert werden als Verallgemeinerung der einfach verketteten Listen mit zwei Nachfolgerverweisen Eine Operation auf binären Bäume mit Knoten (z.b. find, insert ) wird dann definiert durch Delegation der Operation an die Knotenklasse Im gezeigten Beispiel gibt die Klasse BinTree die Verantwortung für einen Teil ihrer Funktionalität an die Hilfsklasse Node ab Als weiteres Beispiel kann eine Methode print definiert werden, welche Informationen über den Knotenwert in der Konsole ausgibt