Pro Informatik 2009 - OOP - Tag 16 - Institut für Informatik

Werbung
Pro Informatik 2009: Objektorientierte Programmierung
Tag 16
Marco Block-Berlitz, Miao Wang
Freie Universität Berlin, Institut für Informatik
07.09.2009
Agenda
Tag 16 – Datenstrukturen
Abstrakte Datentypen, ADT Folge: Stack, Queue, Liste, ADT Menge: Bäume: Binärbäume, Suchbäume, AVL-Bäume,
Prioritätswarteschlangen, Heap, Graphen
ADTs in Java
Tag 17 – Sortieralgorithmen
InsertionSort, BubbleSort, SelectionSort, ShellSort, MergeSort, QuickSort, Binary Tree Sort, HeapSort
Untere Schranke für vergleichsbasierte Sortierverfahren, BucketSort, CountingSort, RadixSort
Tag 18 – Suchalgorithmen
Binärsuche, Breitensuche, Tiefensuche, Backtracking
Klausurvorbereitung
Tag 19 – Klausur
Tag 20 – Letzter Tag
Weitere Projekte am Fachbereich, Klausurnachbesprechung, Grillen?
Pro Informatik 2009: Objektorientierte Programmierung
3
Abstrakter Datentyp
Ein Abstrakter Datentyp (ADT) ist eine Sammlung von Daten, verbunden mit der Definition aller
zulässigen Operationen, die auf sie zugreifen.
Der Zugriff ist nur über die festgelegten Operationen möglich, damit die Daten nach außen gekapselt
sind (Geheimnisprinzip).
Ein ADT beschreibt was die Operationen tun (Spezifikation), aber noch nicht wie sie es tun
(Implementierung). In der Regel gibt es viele Implementierungen für ein ADT.
Ein Objekt eines abstrakten Datentyps wird Abstraktes Datenobjekt (ADO) genannt.
Pro Informatik 2009: Objektorientierte Programmierung
4
Spezifikation vs. Implementierung
Spezifikation beantwortet die Fragen
„WAS leistet das System?“
„WAS kann der Benutzer erwarten?“
Implementierung beantwortet die Fragen
„WIE erbringt das System seine Leistung?“
„WIE ist das System konstruiert?“
Spezifikation
Implementierung
Abstraktes Modell
Abstrakte Invariante
Abstrakte oder konkrete Signatur
Abstrakte Vorbedingungen
Abstrakte Effekte
Konkretes Modell
Konkrete Invariante
Konkrete Signatur
Konkrete Vorbedingungen
Konkrete Effekte
Pro Informatik 2009: Objektorientierte Programmierung
5
ADT Folge
Typische Spezifikation eines ADT „Folge“:
Modell: [T] mit Basistyp T
Invariante: eventuell Längenbeschränkung
Operationen: unterschiedlich - entsprechend unterscheidet man
Stack
Queue
Liste
size, length, count
size, length, count
size, length, count
isEmpty
isEmpty
isEmpty
push
offer, enqueue, append
append*, insert*, add*
peek, top
head, front, peek
get*
pop
poll, dequeue
remove*
remove
remove*
iterate
iterate
iterate
Stack<T>
Queue<T>
List<T>, LinkedList<T>, ArrayList<T>, Vector<T>
* evtl. mit Positionsangabe
Pro Informatik 2009: Objektorientierte Programmierung
6
Implementierung: Stack
Ein Stack (Stapel oder Keller) verwaltet eine geordnete Menge von Objekten, wobei ein Element
angefügt oder das letzte hinzugefügte wieder weggenommen werden kann.
Ein Stack arbeitet also nach dem LIFO-Prinzip (last in first out)
Wichtige Methoden eines Stacks:
push(Objekt)
Objekt pop()
Objekt peek()
boolean isEmpty()
int size()
Iterator<Objekt> iterator()
fügt Objekt als oberstes Element dem Stack hinzu
gibt das oberste Element des Stacks zurück und entfernt es
gibt das oberste Element des Stacks zurück und entfernt es nicht
prüft, ob der Stack leer ist
liefert die Anzahl der im Stack vorhandenen Elemente zurück
liefert ein Iterator-Objekt zurück
In Java erbt Stack von Vector
Pro Informatik 2009: Objektorientierte Programmierung
7
Stack
Ein Stack, welches in der konkreten Implementierung über ein Array realisiert wird.
import java.util.Iterator;
public class Stack {
private int currentIndex;
private Object[] array;
public Stack(int initSize){
currentIndex = -1;
array= new Object[initSize];
}
public void push(Object a) throws OverflowException {
if (currentIndex >= array.length-1) throw new OverflowException("Stack is full");
else {
array[++currentIndex] = a;
}
}
public Object pop() throws UnderflowException {
if (currentIndex < 0) throw new UnderflowException("Stack is empty");
else {
return array[currentIndex--];
}
}
...
Pro Informatik 2009: Objektorientierte Programmierung
8
Stack
...
public Object peek() throws UnderflowException {
if (currentIndex < 0) throw new UnderflowException("Stack is empty");
else {
return array[currentIndex];
}
}
public int size() {
return currentIndex + 1;
}
public Iterator<Object> iterator() {
return new Iterator<Object>() {
int iteratorIndex = currentIndex;
public boolean hasNext() {
if(iteratorIndex >= 0) return true;
return false;
}
public Object next() {
return array[iteratorIndex--];
}
public void remove() {
//should not be used
}
};
}
...
Pro Informatik 2009: Objektorientierte Programmierung
9
Stack
...
public static void main(String[] args) {
Stack s = new Stack(4);
try {
s.push(3);
s.push(4);
s.push(5);
s.push(6);
Iterator<Object> iter = s.iterator();
while(iter.hasNext()) System.out.println(iter.next());
//6 5 4 3
System.out.println(s.peek());
//6
System.out.println(s.pop());
System.out.println(s.pop());
System.out.println(s.pop());
System.out.println(s.pop());
} catch (Exception e) {
e.printStackTrace();
}
//6
//5
//4
//3
}
class OverflowException extends Exception {
public OverflowException(String msg) { super(msg); }
}
class UnderflowException extends Exception {
public UnderflowException(String msg) { super(msg); }
}
}
Pro Informatik 2009: Objektorientierte Programmierung
10
Stack
Laufzeitanalyse für die Operationen
push
pop
peek
isEmpty
size
Pro Informatik 2009: Objektorientierte Programmierung
O(1)
O(1)
O(1)
O(1) , wenn Zähler vorhanden
O(1) , wenn Zähler vorhanden
11
Stack
Wofür kann ein Stack gebraucht werden?
• Abarbeiten von rekursiven Aufrufen
• Speicherverwaltung (und Verwaltung anderer Ressourcen)
• Auswertung von Ausdrücken (Postfix, Infix)
• Verarbeitung von Klammerstrukturen
• Compiler
• Traversieren komplexerer Datenstrukturen
• uvm.
Pro Informatik 2009: Objektorientierte Programmierung
12
Implementierung: Queue
Eine Queue (Schlange, Warteschlange) verwaltet eine geordnete Menge von Objekten, wobei ein
Element angefügt oder das am längsten vorhande Objekt wieder weggenommen werden kann. Wie
bei einer Warteschlange, muss gewartet werden, bis man an der Reihe ist.
Ein Stack arbeitet also nach dem FIFO-Prinzip (first in first out)
Wichtige Methoden einer Queue:
offer(Objekt)
Objekt poll()
Objekt peek()
boolean isEmpty()
int size()
Iterator<Objekt> iterator()
fügt Objekt hinten an die Queue, falls möglich
liefert das vordere Element der Queue und entfernt es
gibt das vorderste Element der Queue zurück und entfernt es nicht
prüft, ob die Queue leer ist
liefert die Anzahl der in der Queue vorhandenen Elemente zurück
liefert ein Iterator-Objekt zurück
In Java ist Queue ein Interface von der es mehrere Implementierungen gibt.
Pro Informatik 2009: Objektorientierte Programmierung
13
Queue
Es gibt unterschiedliche Repräsentationen für eine Queue:
1. Feld, zyklisch benutzt (Längenbeschränkung)
2. Lineares Geflecht, einfach verkettet
tail
head
head
tail
head
3. Zyklisches Geflecht, einfach verkettet
4. Lineares Geflecht, doppelt verkettet
tail
head
head
5. Zyklisches Geflecht, doppelt verkettet
Pro Informatik 2009: Objektorientierte Programmierung
14
Queue
Eine Queue repräsentiert durch ein zyklisch benutztes Feld.
import java.util.Iterator;
public class QueueArray {
private Object[] array;
private int head, count;
public QueueArray(int initSize){
head = 0;
count= 0;
array= new Object[initSize];
}
public void offer(Object o) {
if(count == array.length) return;
array[(head+count++)%array.length] = o;
}
//Null-Operation when full
public Object poll() {
if(count == 0) return null;
Object o = array[head];
head = (head+1)%array.length;
count--;
return o;
}
//return null when empty
...
Pro Informatik 2009: Objektorientierte Programmierung
15
Queue
...
public Object peek() {
if(count == 0) return null;
return array[head];
}
public int size() {
return count;
}
public Iterator<Object> iterator() {
return new Iterator<Object>() {
int iteratorIndex = head;
public boolean hasNext() {
if(iteratorIndex < count) return true;
return false;
}
public Object next() {
return array[(head+iteratorIndex++)%array.length];
}
public void remove() {
//not implemented
}
};
}
...
Pro Informatik 2009: Objektorientierte Programmierung
16
Queue
...
public static void main(String[] args) {
QueueArray q = new QueueArray(3);
q.offer(3);
q.offer(4);
q.offer(5);
q.offer(6);
Iterator<Object> iter = q.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
//3 4 5
System.out.println(q.peek());
//3
System.out.println(q.poll());
System.out.println(q.poll());
System.out.println(q.poll());
System.out.println(q.poll());
//3
//4
//5
//null
}
}
Pro Informatik 2009: Objektorientierte Programmierung
17
Queue
Laufzeitanalyse für die Operationen
offer
poll
peek
isEmpty
size
Pro Informatik 2009: Objektorientierte Programmierung
O(1)
O(1)
O(1)
O(1) , wenn Zähler vorhanden
O(1) , wenn Zähler vorhanden
18
Queue
Wofür kann eine Queue gebraucht werden?
• Ressourcenverwaltung (z.B. bei Betriebssystemen)
• Datenpuffer
• Baum- und Graph-Traversierung
• Verwaltung „realer“ Warteschlangen
• Simulation zeitdiskreter Systeme
• Repräsentation „höherer“ ADT (Mengen, Relationen, ...)
• uvm.
Pro Informatik 2009: Objektorientierte Programmierung
19
Implementierung: Liste
Eine imperative Liste (List, Geflecht) ist eine beliebig manipulierbare Folge mit Positionen 0,1,2, ...
head
Wichtige Methoden einer Liste:
add(Objekt o, int index)
add(Objekt o)
Object remove(int index)
Object get(int index)
boolean isEmpty()
int size()
Iterator<Objekt> iterator()
fügt Objekt o an Stelle index ein
fügt Objekt o am Ende ein
liefert das Objekt an Position index und entfernt es
liefert das Objekt an Position index und entfernt es nicht
prüft, ob die Liste leer ist
liefert die Anzahl der in der Liste vorhandenen Elemente
liefert ein Iterator-Objekt zurück
In Java ist List ein Interface von der es mehrere Implementierungen gibt.
Pro Informatik 2009: Objektorientierte Programmierung
20
Liste
Es gibt unterschiedliche Repräsentationen für eine Liste:
1. wechselnde Felder variabler Länge
2. zyklisches Geflecht, doppelt verkettet, mit innerer Klasse
Pro Informatik 2009: Objektorientierte Programmierung
 ArrayList<T>, Vector<T>
LinkedList<T>
21
Liste
Repräsentation einer doppelt verkettete Liste.
import java.util.Iterator;
public class DoubleLinkedList<T> {
protected class Node {
T value;
Node prev;
Node next;
public Node(T v) {
value = v;
}
}
private Node head = new Node(null);
private Node tail = new Node(null);
private int count = 0;
public DoubleLinkedList() {
head.prev = null;
head.next = tail;
tail.prev = head;
tail.next = null;
}
...
Pro Informatik 2009: Objektorientierte Programmierung
22
Liste
...
public void add(T value, int index) throws IndexOutOfBoundsException {
Node cursor = get(index);
Node newItem = new Node(value);
newItem.prev = cursor;
newItem.next = cursor.next;
cursor.next.prev = newItem;
cursor.next = newItem;
count++;
}
public void add(T value) {
add(value, count);
}
public T remove(int index) throws IndexOutOfBoundsException {
//Übungsaufgabe
}
...
Pro Informatik 2009: Objektorientierte Programmierung
23
Liste
...
public Node get(int index) throws IndexOutOfBoundsException {
if (index < 0 || index > count) {
throw new IndexOutOfBoundsException();
} else {
Node cursor = head;
for (int i = 0; i < index; i++) {
cursor = cursor.next;
}
return cursor;
}
}
public boolean isEmpty() {
return count == 0;
}
public int size() {
return count;
}
...
Pro Informatik 2009: Objektorientierte Programmierung
24
Liste
...
public Iterator<Node> iterator() {
return new Iterator<Node>() {
Node cursor = head;
public boolean hasNext() {
return cursor.next != null;
}
public Node next() {
cursor = cursor.next;
return cursor;
}
public void remove() {
//not implemented
}
};
}
...
Pro Informatik 2009: Objektorientierte Programmierung
25
Liste
...
public String toString() {
StringBuffer result = new StringBuffer();
result.append("(head) - ");
Node temp = head;
while (temp.next != tail) {
temp = temp.next;
result.append(temp.value + " - ");
}
result.append("(tail)");
return result.toString();
}
public static void main(String argv[]) {
DoubleLinkedList<Integer> list = new DoubleLinkedList<Integer>();
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7, 2);
System.out.println(list);
list.remove(list.size());
list.remove(1);
System.out.println(list);
}
}
Pro Informatik 2009: Objektorientierte Programmierung
26
Liste
Laufzeitanalyse für die Operationen (bei Verwendung eines Arrays)
add(Object o, int index)
remove(int index)
remove(Object o)
get(int index)
isEmpty
size
merge
O(n)
O(n)
O(n)
O(1)
O(1) , wenn Zähler vorhanden
O(1) , wenn Zähler vorhanden
O(n)
Laufzeitanalyse für die Operationen (bei Verwendung eines Geflechts)
add(Object o, int index)
remove(int index)
remove(Object o)
get (int index)
isEmpty
size
merge
Pro Informatik 2009: Objektorientierte Programmierung
O(n)
O(n)
O(n) bei einfach verkettetem Geflecht
O(1) bei doppelt verkettetem Geflecht
O(n)
O(1) , wenn Zähler vorhanden
O(1) , wenn Zähler vorhanden
O(1)
27
PAUSE
Pro Informatik 2009: Objektorientierte Programmierung
28
ADT Menge
Typische Spezifikation eines ADT „Menge“:
Modell: {T} mit Basistyp T
Invariante: eventuell Längenbeschränkung
Operationen: unterschiedlich - entsprechend unterscheidet man
elementOf
isEmpty
size
add, remove
union, intersection, difference, subset
iterate
In Java gibt es unter der Schnittstelle java.util.Set eine Vielzahl von verschiedenen
Implementierungen.
Pro Informatik 2009: Objektorientierte Programmierung
29
Bäume
Ein freier Baum ist in der Informatik definiert als kreisfreier zusammenhängender Graph.
G = (E,V), mit E Menge aller Kanten (edges) und V Menge aller Knoten (vertices)
Ein (Wurzel-)Baum ist ein freier Baum B mit einer ausgezeichneter Knoten als „Wurzel“ w
Pro Informatik 2009: Objektorientierte Programmierung
30
Bäume
Terminologie
Wurzel
Vater
Blatt
Kind
Kind
Teilbaum
Unterbaum
Pro Informatik 2009: Objektorientierte Programmierung
31
Bäume
Terminologie
0
1
2
3
Grad (degree) eines Knotens = Anzahl der Kinder
(= Anzahl der nichtleeren Teilbäume des zugehörigen Unterbaums)
Ebene, Stufe (level) eines Knotens = Weglänge von der Wurzel
Höhe (height) eines nichtleeren Baums = maximale Ebene
vollständiger Baum: alle Ebenen sind vollständig besetzt, außer eventuell der untersten
Pro Informatik 2009: Objektorientierte Programmierung
32
Bäume
Terminologie
balancierter Baum
Ein balancierter Baum garantiert
eine maximale Höhe von
entarteter Baum
Die Höhe nähert sich n
Pro Informatik 2009: Objektorientierte Programmierung
33
Binärbäume
Ein Binärbaum ist ein gewurzelten Baum, bei dem jeder Knoten höchstens zwei Kindknoten besitzt.
Ein Binärbaum mit Höhe h hat folgende Eigenschaften:
• maximal 2h+1-1 Knoten,
• maximal 2h Blätter
Bei einer vorgegebenen Knotenzahl n hat ein Binärbaum mindestens die Höhe
Pro Informatik 2009: Objektorientierte Programmierung
34
Binärbäume
Implementierung eines Binärbaums
public class BinTree<T> {
static class Node<T> {
Node<T> left;
T value;
Node<T> right;
Node(T v) {
left = null;
right = null;
value = v;
}
Node(T v, Node<T> l, Node<T> r) {
left = l;
right = r;
value = v;
}
}
private Node<T> root;
public BinTree() {
root = null;
}
...
Pro Informatik 2009: Objektorientierte Programmierung
35
Binärbäume
Implementierung eines Binärbaums
...
public static void main(String[] args) {
BinTree<Integer> b = new BinTree<Integer>();
b.root = new Node<Integer>(5);
b.root.left = new Node<Integer>(2);
b.root.right = new Node<Integer>(7, new Node<Integer>(6), new Node<Integer>(9));
}
}
5
7
2
6
Pro Informatik 2009: Objektorientierte Programmierung
9
36
Traversierung
Es gibt mehrere Möglichkeiten einen Baum zu traversieren (= „mit jedem Element wird etwas
gemacht“)
• Tiefendurchlauf
• Alternativen: Preorder, Inorder, Postorder
• Breitendurchlauf
 Siehe Vorlesung zu Suche
Pro Informatik 2009: Objektorientierte Programmierung
37
Suchbäume
Suchbäume sind Bäume zur Repräsentation einer linear geordneter Mengen. Wir beschränken uns
hier auf binäre Suchbäume.
Invariante eines binären Suchbaums:
Die Wurzel ist größer als alle Elemente im linken Teilbaum und kleiner als alle Elemente im rechten
Teilbaum, und die Teilbäume sind ebenfalls binäre Suchbäume.
Die geordnetete Menge { 1, 3, 4, 5, 7, 9, 11 } kann folgendermaßen repräsentiert werden:
5
7
3
1
11
4
9
Es gibt in der Regel mehrere Darstellungen für eine Menge
Pro Informatik 2009: Objektorientierte Programmierung
38
Suchbäume
In einem Suchbaum kann effizient nach einem Element gesucht werden und somit überprüft werden
ob ein Element sich in der Menge befindet oder nicht.
Algorithmus um nach Element x zu suchen:
In jedem Teilbaum von der Wurzel nach unten, wobei an jedem Scheideweg die Entscheidung
aufgrund der Suchbaum-Invariante getroffen wird. Wird x gefunden, gebe true zurück. Enden wir an
einem Blatt und haben x nicht gefunden, gebe false zurück.
(wenn Suchelement größer als Wurzel, gehe nach rechts, sonst links)
5
7
3
1
11
4
9
Die Laufzeit beträgt O(h) = O(log n). Wobei h die Höhe des Suchbaums ist und
n die Anzahl von Knoten im Suchbaum.
Pro Informatik 2009: Objektorientierte Programmierung
39
Suchbäume
Um ein neues Element in einen Suchbaum einzufügen, verfahren wir ähnlich:
Algorithmus um Element x einzufügen:
Suche nach Element x mit dem Suchalgorithmus. Wenn x bereits vorhanden, tue nichts. Ansonsten
endet die Suche bei einem Blattknoten. Füge x an diesen Blattknoten gemäß Suchbaum-Invariante.
5
7
3
1
4
6
11
9
Die Laufzeit entspricht der Laufzeit vom Suchen, also ebenfalls O(h) = O(log n).
Pro Informatik 2009: Objektorientierte Programmierung
40
Suchbäume
Um ein Element zu entfernen, müssen verschiedene Situationen betrachtet werden.
Algorithmus um Element x zu entfernen:
Wenn x ein Blatt ist, entferne das Blatt einfach.
3
3
1
Wenn x nur einen Nachfolger hat, setze den Nachfolger an die Position von x
3
1
1
Pro Informatik 2009: Objektorientierte Programmierung
41
Suchbäume
Algorithmus um Element x zu entfernen:
Wenn x zwei Nachfolger hat gibt es zwei Möglichkeiten:
Setze den linken Teilbaum an die Position von x und den rechten Teilbaum rechts an den linken
gemäß Suchbaum-Invariante.
(oder analog spiegelbildlich)
2
9
4
2
12
8
4
6
8
5
12
7
6
5
7
Pro Informatik 2009: Objektorientierte Programmierung
 drohende Unausgeglichenheit
(Entartung)
42
Suchbäume
Algorithmus um Element x zu entfernen (besser):
Ersetze x durch seinen symmetrischen Vorgänger (größter Wert im linken Teilbaum).
(entsprechend auch symmetrischer Nachfolger möglich)
9
8
2
12
2
4
12
4
8
6
5
6
7
Pro Informatik 2009: Objektorientierte Programmierung
Höhe bleibt erhalten,
Entartung immer noch möglich
5
7
43
Balancierte Bäume
Die Entartung von Bäumen stellt ein großes Problem für die Performance der Operationen dar. Es
gibt eine Klasse von balancierten Bäumen, die nach jeder Operation den Baum an der Stelle der
Änderung neu balancieren.
• AVL-Bäume
• Rot-Schwarz-Bäume
• 2-3-4-Bäume
• B-Bäume
• B+-Bäume
• B*-Bäume
• Treap
• AA-Bäume
• Splay-Bäume
Pro Informatik 2009: Objektorientierte Programmierung
44
AVL-Bäume
Ein Suchbaum heißt k-ausgeglichen, wenn für jeden Knoten die Höhen seiner beiden Teilbäume um
höchstens k voneinander abweichen.
Ein AVL-Baum ist ein 1-ausgeglichener Suchbaum (Adelson-Velsky und Landis, 1962).
Invariante eines AVL-Baums:
Invariante eines binären Suchbaums +
für jeden Knoten k gilt: die Höhen h1 und h2 der beiden Teilbäume unterscheiden sich um höchstens 1
Suchen, Einfügen und Löschen in einem AVL-Baum:
Genauso wie beim binären Suchbaum + gegebenenfalls ausgleichen („rebalancing“) durch Rotationen.
Pro Informatik 2009: Objektorientierte Programmierung
45
AVL-Bäume
Einfache Rotation:
x
0
-2
y
A
<x
B
>x
<y
-1
C
>y
y
0
x
A
<x
B
>x
<y
C
>y
Geht jedoch schief, wenn an Teilbaum B erweitert wird!
Pro Informatik 2009: Objektorientierte Programmierung
46
AVL-Bäume
Doppelte Rotation:
-2
-2
x
0
x
+1
z
-1
0
0
x
y
0
z
0
y
A
<x
B1
>x
<y,z
y
B2
<z
>x,y
z
C
>z
Pro Informatik 2009: Objektorientierte Programmierung
A
<x
B1
>x
<y,z
B2
<z
>x,y
C
>z
A
<x
B1
>x
<y,z
B2
<z
>x,y
C
>z
47
Prioritätswarteschlange
Wir kennen bereits die einfachen Warteschlangen (Queue). Eine Prioritätswarteschlange (Priority
Queue) erweitert die bisherigen Warteschlangen, indem jedes Element ein Schlüssel (eine Priorität)
mitgegeben wird, der die Reihenfolge der Abarbeitung der Elemente bestimmt.
Wichtige Methoden einer Priority Queue:
insert(Objekt, Schlüssel)
insert(Objekt)
Objekt extractMin()
fügt Objekt in die Priority Queue an die Stelle gemäß Schlüssel
fügt Objekt in die Priority Queue, (Schlüssel implizit im Objekt)
liefert das Element mit dem kleinsten Schlüssel bzw. der höchsten
Priorität und entfernt es aus der Priority Queue
Objekt peek()
liefert das Element mit dem kleinsten Schlüssel bzw. der höchsten
Priorität, entfernt es aber nicht
remove(Objekt)
entfernt Objekt aus der Priority Queue
decreaseKey(Objekt, Schlüssel)
verringert den Schlüssel bzw. erhöht die Priorität vom
Objekt in der Priority Queue
In Java basiert der Schlüssel auf der Implementierung der Schnittstelle Comparable oder Comparator
Siehe java.util.PriorityQueue
Pro Informatik 2009: Objektorientierte Programmierung
48
Prioritätswarteschlange
Typische Repräsentationen für Prioritätswarteschlangen:
1.
2.
Als Array oder Liste (nicht sortiert)
insert(Objekt, Schlüssel)
Objekt extractMin()
remove(Objekt)
decreaseKey(Objekt, Schlüssel)
O(1)
O(n)
O(1) bei doppelt verkettetem Geflecht, sonst O(n)
O(1)
Als Array oder Liste (sortiert)
insert(Objekt, Schlüssel)
Objekt extractMin()
remove(Objekt)
decreaseKey(Objekt, Schlüssel)
O(n)
O(1)
O(1) bei doppelt verkettetem Geflecht, sonst O(n)
O(n)
3.
Als Array von Warteschlangen für begrenzte Anzahl von Schlüsseln
alles O(1)
4.
Als Heap
alles O(log n)
Pro Informatik 2009: Objektorientierte Programmierung
49
Heap
Ein Heap (Haufen, Halde) ist ein Baum, wo die Elemente mit Schlüsseln versehen sind. Häufig werden
auch die Elemente selbst als Schlüssel verwendet.
Invariante eines Min-Heaps:
Der Heap ist (links-)vollständig und partiell geordnet (Jeder Knotenwert ist kleiner oder gleich der
Knotenwerte seiner Kinder).
Invariante eines Max-Heaps:
Der Heap ist (links-)vollständig und partiell geordnet (Jeder Knotenwert ist größer oder gleich der
Knotenwerte seiner Kinder).
Wir beschränken uns auf Binärheaps (jeder Knoten hat höchstens zwei Kindknoten), aber es gibt
noch andere Sorten von Heaps:
• Binomial-Heap
• Fibonacci-Heap
• Treap
• Radix-Heap
Pro Informatik 2009: Objektorientierte Programmierung
50
Binärheap
Ein Binärheap ist ein Heap, wo jeder Knoten höchstens zwei Kindknoten besitzt.
Er ist (links-)vollständig und partiell geordnet.
Beispiel:
2
9
7
13
20
7
15
11
18
8
Ein Binärheap unterstützt sehr effizient die üblichen Operationen einer Prioritätswarteschlange:
insert, extractMin, decreaseKey, remove
Pro Informatik 2009: Objektorientierte Programmierung
51
Binärheap
Algorithmus um Element x einzufügen:
insert
Element x hinten anhängen, dann solange mit dem jeweils nächsten Vorgänger vertauschen,
solang x kleiner ist (heapify).
2
2
9
7
13
20
7
15
8
11
6
9
6
18
13
20
7
15
8
11
18
7
Laufzeit: O(h) = O(log n)
Pro Informatik 2009: Objektorientierte Programmierung
52
Binärheap
Algorithmus um Element x zu entfernen:
remove
Vertausche x mit dem letzten Element y im Heap und entferne x. Dann wird y solange mit dem
jeweils kleineren der beiden Nachfolger-Werte vertauscht, solang es noch größer als einer der beiden
ist (heapify).
2
7
9
7
13
20
7
15
11
8
9
7
18
13
20
8
15
11
18
2
Analog dazu das Minimum aus der Menge zu entfernen: Entferne die Wurzel
extractMin
Analog auch das Ändern eines Schlüssels: Vertauschen bis Invariante wieder hergestellt decreaseKey
Laufzeiten: alle O(h) = O(log n)
Pro Informatik 2009: Objektorientierte Programmierung
53
Binärheap
Ein Binärheap kann als Baumstruktur repräsentiert werden oder auch effizient als Array mit
Breitensuch-Anordnung (Wurzel hat Index 1).
1
2
4
8
3
7
5
13
9
20
2
15
10
6
7
9
11
i= 2n + j ,
8
k1 = 2i ,
2
7
9 13 7 11 18 20 15 8
1
2
3
4
5
6
7
8
9
18
n = Ebene
k2 = 2i+1
10
index(x) = i ⇔ index(left(x)) = 2i ∧ index(right(x)) = 2i+1
Pro Informatik 2009: Objektorientierte Programmierung
7
54
Graph
Ein Graph besteht aus einer Menge an Knoten V und einer Menge an Kanten E = V x V
b
b
a
a
d
c
gerichteter Graph
„d ist Nachfolger von a“
„a ist Vorgänger von d“
Pro Informatik 2009: Objektorientierte Programmierung
d
c
ungerichteter Graph
Relation E ist symmetrisch
(a,d) є E ⇔ (d,a) є E
„d ist Nachbar von a“
55
Graph
Ein Graph kann als Adjazenzliste oder Adjazenzmatrix gespeichert werden:
Adjazenzliste
a: b , c , d
b: b , c
c: a
d:
b
a
d
Pro Informatik 2009: Objektorientierte Programmierung
c
Adjazenzmatrix
a b c d
a
x x x
b
x x
c x
d
56
Graph
Auf einen Graph werden oft Operationen ausgeführt:
• um ein Knoten zu finden
 siehe Vorlesung: Suche
• um einen Weg von einem Knoten zu einem anderen Knoten zu finden
Ein Weg (path) ist eine Folge von Knoten e0 , e1 , e2 , . . . , en, n ≥ 0
Sehr viele Sachverhalten werden in der Informatik als Graphen repräsentiert. Daher finden man Sie in
vielen Anwendungsgebieten wieder:
• Verkehrsnetze, z.B. Navis
• Kommunikationsnetze, z.B. Internet
• Energienetze
• Netzpläne
• Spiele
• uvm.
Pro Informatik 2009: Objektorientierte Programmierung
57
Herunterladen