1 Übersicht Dynamische Mengen Dynamische

Werbung
Übersicht
Elementare Datenstrukturen
• Stapel & Warteschlangen
• Verkettete Listen
Datenstrukturen & Algorithmen
• Bäume
Matthias Zwicker
Universität Bern
Frühling 2009
2
Dynamische Mengen
Dynamische Mengen
• Daten speichern und abfragen
• Mögliche Operationen
Dynamische Menge S, Schlüssel k, Referenz
auf Record x
• Records aus Schlüssel und Satellitendaten
class Record {
int key;
SatelliteData data;
}
– Search(S,k)
– Insert(S,x)
Insert(S x)
– Delete(S,x)
– Minimum(S)
– Maximum(S)
– Successor(S,x)
– Predecessor(S,x)
class SatelliteData{
String
g name;
;
String address;
...
}
3
4
Datenstrukturen
Stapel & Warteschlangen
• Geeignete Datenstruktur je nach
Operationen, die effizient unterstützt
werden soll
• Dynamische Mengen mit effizientem
Einfügen und Entfernen in O(1)
– Insert(S,x)
– x = Remove(S)
• Zeitkomplexität wird als Funktion der
Grösse n der Menge gemessen
Stapel
• Einfügen und Entfernen mit last-in-, firstout-Strategie (LIFO)
Warteschlangen
• Einfügen und Entfernen mit first-in-, firstout-Strategie (FIFO)
5
6
1
Stapel (LIFO)
Stapel
• Einfügen = push, Entfernen = pop
• Beispiel
push(4); push(6); pop; push(8); pop; pop;
• Hier: Implementation mit Feld
– Implementation mit anderen Datenstrukturen
möglich
– Elemente hier Integers der Einfachkeit halber,
g
Records mit Satellitendaten funktioniern gleich
1 23 4 5 6 7 8
Stack S 161410 8 7
top = 5
• Statusvariable top
1 23 4 5 6 7 8
Stack S 161410 8 7
top = 5
class Stack {
private int top;
private int S[];
/* constructor,
methods push, pop */
}
7
8
Anwendung
Warteschlange (FIFO)
• Nicht-rekursiver QuickSort mit Stack
• Einfügen = queue, Entfernen = dequeue
• Hier: Implementation mit Feld
void quickSort(int array[], int left, int right)
{
Stack leftStack = new Stack();
Stack rightStack = new Stack();
leftStack.push(left); rightStack.push(right);
while(!leftStack.isEmpty())
{
left = leftStack.pop(); right = rightStack.pop();
if(left<right)
{
int p = partition(array, left, right);
leftStack.push(left); rightStack.push(p-1);
leftStack.push(p+1); rightStack.push(right);
}
}
}
– Implementation mit anderen Datenstrukturen
möglich
• Statusvariable
S
i bl kopf,
k f ende
d
Queue Q
1 23 4 5 6 7 8
10 8 7 1614
kopf = 3
ende = 7
class Queue {
private int kopf, ende;
private int Q[];
/* constructor,
methods queue,
dequeue */
}
9
10
Warteschlange
Anwendungen
• Beispiel
• Verwaltung von Aufträgen, die mittels
einer first-come, first-serve Strategie
bearbeitet werden sollen
queue(6); queue(9); queue(11); dequeue; dequeue
Queue Q
1 23 4 5 6 7 8
10 8 7 1614
kopf = 3
ende = 7
11
12
2
Verkettete Listen
Verkettete Listen
• Vorteil gegenüber Feldern: maximale
Anzahl Elemente ist dynamisch
• Listenelemente bestehen aus
– Schlüssel (oder Referenz auf andere Daten)
– Zeiger auf nachfolgendes Listenelement
– Doppelt verkettet: Zeiger auf vorheriges
Listenelement
• Varianten
–
–
–
–
Einfach verkettete Liste
Doppelt verkettete Liste
Zyklische Liste
Sortierte Liste
• Zusätzlich: Zeiger kopf auf erstes Listenelement
• Beispiel
class LinkedList {
private class ListElement {
ListElement prev, next;
int key;
}
ListElement head;
/* methods to add elements, etc. */
}
13
Durchsuchen
14
Einfügen
• Doppelt verkettete Liste
ListElement Search(int k) {
ListElement cur = head;
while(head!=null && k!=cur.key)
cur = cur.next;
return cur;
}
void insert(ListElement e) {
e.next = head;
if(head!=null)
head.prev = e;
head = e;
e.prev = null;
}
15
Entfernen
16
Wächter
• Dummy Objekt, um Randbedingungen zu
vereinfachen
• Doppelt verkettete Liste
void delete(ListElement d) {
if(d.prev!=null)
d.prev.next = d.next;
else
head = d.next;
if(d.next!=null)
d.next.prev = d.prev;
}
• Verknüpft Liste zu einem Ring (zyklische Liste)
• Zeiger auf Dummy bezeichet mit nil, ersetzt kopf
• Hier doppelt kerkettete Liste
class CyclicList {
private class ListElement {
ListElement prev, next;
int key;
}
ListElement nil;
/* methods to add elements, etc. */
}
17
18
3
Einfügen in Liste mit Wächter
Parameterisierte Klasse in Java
class LinkedList<T> {
private class Element<T> {
private Element prev, next;
private T data;
}
private Element<T> nil;
LinkedList()
() {
nil = new T();
nil.next = nil;
nil.prev = nil;
}
void insert(T e) {...}
/* add other operations */
}
void insertElement(ListElement e) {
e.next = nil.next;
nil.next.prev = e;
nil.next = e;
e.prev = nil;
}
19
20
Zeiger und Objekte mit Feldern
Zeiger und Objekte mit Feldern
• Was, wenn eine Programmiersprache keine
Zeiger zur Verfügung stellt?
• Liste
kopf
9
16
4
1
• Mehrfelddarstellung
• Implementiere Zeiger und Objekte mit
Feldern
1 2 3 4 5 6 7 8
next
key
prev
• Einfelddarstellung
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
21
22
Allokieren und Freigeben von Objekten
Allokieren und Freigeben
• Wollen Operationen auf dynamischen Listen
anbieten wie vorher
x = allocateObject();
insert(x);
– Insbesondere, allokieren und einfügen neuer Objekte
– Allokieren ähnlich „new()“ in Java
– Brauchen Zugriff auf freie Elemente in Felder
key[x] = 25;
delete(5);
• Unterhalte zwei Listen
1 2 3 4 5 6 7 8
– Liste mit Daten
– Liste mit freien Objekten
next
key
prev
1 2 3 4 5 6 7 8
next
key
prev
1 2 3 4 5 6 7 8
next
key
prev
next
key
prev
23
24
4
Gerichtete Bäume
Binäre Bäume
• Verallgemeinerung von linearen Listen mit
Verkettung zu einer Baumstruktur
• Wie bei Listen: Elemente enthalten
– Schlüssel (oder Referenzen auf Satellitendaten)
– Referenzen zur Verkettung
• Grundlage für viele Algorithmen
– z.B. Suchen
• Heute
– Binäre Bäume
– Bäume mit unbeschränktem Grad
25
Bäume mit unbeschränktem Grad
26
kd-Bäume
• Räumliche Datenstruktur
• Speichert Position von Punkten im ddimensionalen Raum
• Erlaubt effiziente Abfragen wie
– Fi
Finde
d nächsten
ä ht N
Nachbarn
hb
– Finde k-nächste Nachbarn
– Finde alle Nachbarn in einem gewissen Radius
• Anwendungen
– Künstliche Intelligenz
– Computergrafik
27
Konstruktion
28
Konstruktion
• Viele Varianten, diese hier führt zu einem
balancierten kd-Baum
node constructKdTree (set of points, axis)
if set of points is empty return null;
else {
select median point along axis
split set of points into set below and above median
create node with location of median point
node.left = kdtree(points below median, cycle(axis))
node.right = kdtree(points above median, cycle(axis))
return node
}
}
Menge von Punkten in 2D
29
kd-Baum
30
5
Einfügen
Einfügen
• Eingabe: neuer Punkt
• Ausgabe: kd-Baum der neuen Punkt enthält
• Ablauf
– Traversiere kd-Baum bis zu einem Blatt
• Bei jedem Knoten, entscheide basierend auf
Vergleich von Position von Knoten und neuem
Punkt, in welchen Teilbaum zu gehen
– Wenn Blatt erreicht, erstelle neuen Knoten,
der dem Blatt als Kind angehängt wird
Neuer Punkt (3,5)
31
(3,5)
32
Nächster Nachbar
• Input: Neuer Punkt
• Output: nächster Punkt im kd Baum
• Ablauf
– Traversiere kd Baum bis zu Blatt, in das der
Abfragepunkt fällt
– Blattknoten ist Kandidat für nächster Nachbar
– Traversiere Baum zurück zur Wurzel, bei jedem
Knoten
• Falls Knoten näher als bisheriger Kandidat, wird neuer
Kandidat
• Falls im anderen Teilbaum näherer Punkt möglich,
traversiere anderen Teilbaum
33
6
Herunterladen