Kapitel 4: Bäume / Graphen Gliederung 1. Motivation - fbi.h

Werbung
Kapitel 4: Bäume / Graphen
Gliederung
1.  Motivation / Grundlagen
2.  Sortierverfahren
3.  Elementare Datenstrukturen / Anwendungen
4.  Bäume / Graphen
5.  Hashing
6.  Algorithmische Geometrie
4/6, Folie 1
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Motivation (Teil 1)
gegeben:
seien n Städte (/* hier A,B, ...,E */) und damit ein ungerichteter
Graph G (/* in dem zwischen je zwei Städten eine Kante
vorkommt */)
B
A
C
D
gesucht:
4/6, Folie 2
© 2014 Prof. Steffen Lange
E
Teilgraph G‘ von G, in dem es eine Verbindung von jeder
Stadt zu jeder anderen Stadt gibt (/* Telefon- bzw.
Stromleitungsnetz */)
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Motivation (Teil 1, cont.)
... mögliche Lösungen
B
B
A
C
D
4/6, Folie 3
© 2014 Prof. Steffen Lange
D
E
-
HDa/FbI
A
C
-
Datenstrukturen
E
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Grundbegriffe
• 
es sei G = (V,E) ein ungerichteter Graph
• 
G ist zusammenhängend, falls es zu je zwei Knoten x,y ∈ V einen Weg
w = (v1,v2,...,vn-1,vn) von x nach y in G gibt (/* d.h. v1 = v und vn = v‘ und
{ vi,vi+1 } ∈ E für alle i mit 1 ≤ i ≤ n - 1 */)
G hat einen Kreis, falls es einen Knoten x ∈ V und einen Weg
w = (v1,v2,...,vn-1,vn) mit n > 3 von x nach x gibt (/* d.h. v1 = vn =x */), in
dem jeder Knoten außer x nur einmal vorkommt
• 
• 
es sei der Graph G‘ = (V‘,E‘) ein Teilgraph von G (/* d.h. es gilt
E‘ ⊆ V‘×V‘, V‘ ⊆ V, und E‘ ⊆ E */)
G‘ = (V‘,E‘) ist ein aufspannender Baum von G, falls gilt:
• 
V‘ = V
• 
G‘ ist kreisfrei
• 
G‘ ist zusammenhängend.
4/6, Folie 4
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Illustration
B
B
A
C
A
C
D
D
E
E
B
A
C
D
4/6, Folie 5
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
E
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  eine einfache Beobachtung
• 
es sei G = (V,E) ein ungerichteter Graph mit n Knoten und G‘ = (V‘,E‘)
ein aufspannender Baum in G
Dann hat G‘ genau n - 1 viele Kanten.
... falls G‘ weniger Kanten hat, kann G‘ nicht zusammenhängend sein
... falls G‘ mehr Kanten hat, kann G‘ nicht kreisfrei sein
4/6, Folie 6
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Aufgabenstellung
Eingabe:
ein ungerichteter zusammenhängender Graph G = (V,E)
Ausgabe:
ein aufspannender Baum G‘ = (V‘,E‘) in G
... später betrachten wir dieselbe Aufgabenstellung für kantenbewertete
ungerichtete zusammenhängende Graphen und sind daran interessiert,
einen aufspannenden Baum mit minimalem Gewicht zu bestimmen
4/6, Folie 7
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Motivation (Teil 2)
gegeben:
seien n Städte (/* hier A,B, ...,E */) und damit ein ungerichteter
Graph G (/* ... und die Kanten haben die Entfernungen
zwischen den Städten als Gewichte */)
B
5
3
5
C
A
5
5
5
D
gesucht:
4/6, Folie 8
© 2014 Prof. Steffen Lange
3
5
5
5
E
Teilgraph G‘ von G, in dem es eine Verbindung von jeder
Stadt zu jeder anderen Stadt gibt und die Gesamtlänge der
Verbindungen minimal sein soll
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Motivation (Teil 2, cont.)
... eine Lösung (/* Gesamtlänge
der Verbindungen = 20 */)
B
5
3
A
5
D
4/6, Folie 9
3
© 2014 Prof. Steffen Lange
5
-
5
HDa/FbI
-
Datenstrukturen
3
5
5
D
E
5
A
5
5
5
3
5
C
5
5
B
5
5
C
... beste Lösung (/* Gesamtlänge
der Verbindungen = 16 */)
5
E
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Datenstruktur
• 
4/6, Folie 10
eine Menge M von Kanten (/* dient zur Verwaltung der in G‘ potentiell
aufzunehmenden Kanten */)
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  „erste“ algorithmische Idee
(1)  setze M = E und V‘ = ∅ und E‘ = ∅
(2)  solange E‘ < | V | - 1
a)  wähle eine Kante e = { x,y } aus M und streiche e aus M
b)  setze V* = V‘ ∪ { x,y } und E* = E‘ ∪ { e }
c)  teste, ob der Graph G* = (V*,E*) kreisfrei ist
falls ja, so setze V‘ = E* und E‘ = E*
falls nein, so ändere V‘ und E‘ nicht
• 
• 
... die Laufzeit hängt offenbar davon ab, wie effizient man in c) testen
kann, ob G* = (V*,E*) kreisfrei ist
... Verfeinerung: diesen Test möglichst einfach realisieren
4/6, Folie 11
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Hintergrund für eine Verfeinerung der algorithmischen Idee
• 
es sei G = (V,E) ein ungerichteter Graph
• 
es seien die Graphen G1 = (V1,E1) und G2 = (V2,E2) kreisfreie
zusammenhängende Teilgraphen von G mit V1 ∩ V2 = ∅
• 
es sei e = { x,y } ∈ E mit x ∈ V1 und y ∈ V2
Dann ist G* = (V*,E*) mit V* = V1 ∪ V2 und E* = E1 ∪ E2 ∪ { e } ein
kreisfreier zusammenhängender Teilgraph von G.
G
... es ist offenbar essentiell V1 und V2 zu kennen und
die Menge E1 ∪ E2
4/6, Folie 12
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Illustration
G1 = (V1,E1)
B
B
A
C
D
G2 = (V2,E2)
A
C
D
E
E
B
A
C
G* = (V*,E*), wobei
e = { B,E } ist
D
4/6, Folie 13
© 2014 Prof. Steffen Lange
-
HDa/FbI
E
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  Grundbegriff
4/6, Folie 14
• 
es sei O eine Menge von Objekten
• 
es sei K = { M1,M2,...,Mk } (/* mit 1 ≤ k ≤ n */) eine Menge von nicht-leeren
Teilmengen von O
• 
K ist eine Klasseneinteilung der Menge O, falls gilt:
• 
für alle alle i,j mit 1 ≤ i,j ≤ k gilt: Mi ∩ Mj = ∅ (/* die Mengen von K sind
paarweise disjunkt */)
• 
O = M1 ∪ M2 ∪ ... ∪ Mk (/* jedes Objekt aus O kommt in einer Menge
von K vor */)
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen aufspannender Bäume
u  verfeinerte algorithmische Idee
(1)  setze M = E, E‘ = ∅ und bilde die Klasseneinteilung K = { { x } | x ∈ V }
(2)  solange E‘ < | V | - 1
a)  wähle eine Kante e = { x,y } aus M und streiche e aus M
b)  bestimme V1,V2 ∈ K mit x ∈ V1 und y ∈ V2
c)  teste, ob V1 ≠ V2 gilt
• 
• 
falls ja, so setze E‘ = E‘ ∪ { e }, streiche V1 und V2 aus
der Klasseneinteilung K und füge die Menge V‘ = V1 ∪ V2
zur Klasseneinteilung K hinzu (/* für alle V* ∈ K ist der
durch V* induzierte Teilgraph G* = (V*,E(V*)) kreisfrei und
zusammenhängend; V(E*) = { { x,y } ∈ E‘ | x,y ∈ V* } */)
falls nein, so ändere E‘ nicht
... zur Verwaltung der Klasseneinteilung K verwendet man eine
spezielle Datenstruktur (/* Union-Find-Struktur genannt */)
4/6, Folie 15
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen minimal aufspannender Bäume
u  Illustration
M = { { A,B },{ A,C },{ B,C },{ A,D }, ... }
E‘ = ∅
K = { { A },{ B },{ C },{ D },{ E } }
B
M = { { A,C },{ B,C },{ A,D }, ... }
E‘ = { { A,B } }
K = { { A,B },{ C },{ D },{ E } }
D
M = { { B,C },{ A,D }, ... }
E‘ = { { A,B },{ A,C } }
K = { { A,B,C },{ D },{ E } }
4/6, Folie 16
© 2014 Prof. Steffen Lange
-
HDa/FbI
A
C
E
M = { { A,D }, ... }
E‘ = { { A,B },{ A,C } }
K = { { A,B,C },{ D },{ E } }
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Grundidee
• 
es sei O = { o1,...,on } die Grundmenge der betrachteten Objekte (/* in
unserem Fall sind das die Knoten von G */)
• 
• 
wir interessieren uns für die Verwaltung von Klasseneinteilungen K von
O (/* d.h. K = { M1,...,Mk } mit M1 ∪ ... ∪ Mk = O und die Mengen
M1,...,Mk sind paarweise disjunkt */)
die Anzahl der verwalteten Mengen ändert sich über die Zeit
• 
zentrale Operation: Vereinigung disjunkter Mengen
... Zugriff auf die Mengen ???
4/6, Folie 17
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Namensgebung von Mengen
• 
• 
o1,...,on dienen als Namen für die Einermengen { o1 },...,{ on }
allgemein dient ein ausgezeichnetes Element o ∈ M als Name für eine
Teilmenge M ⊆ O
u  relevante Operation
4/6, Folie 18
• 
union(oi,ok) – Menge der verwalteten Mengen ändern, indem die
Mengen mit den Namen oi bzw. ok vereinigt werden
• 
find(o) – den Namen der Menge bestimmen, die aktuell das Objekt o
enthält
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Realisierung von Union-Find-Strukturen (/* konzeptionell */)
repräsentiere Mengen als Bäume beliebiger Ordnung
• 
• 
• 
• 
4/6, Folie 19
jeder Knoten hat ein Objekt als Label
jeder Knoten hat einen Zeiger auf seinen Vater
die Wurzel hat einen Zeiger auf sich selbst
das Label der Wurzel dient als Name für diese Menge
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Illustration
einelementige Mengen
{2}
2
mehrelementige Mengen
1
3
{ 1,3,5,7 }
5
7
4/6, Folie 20
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Realisierung von Union-Find-Strukturen (/* konzeptionell */)
Find-Operation
... gib das Label der Wurzel des Baums
zurück, in dem das Objekt o gespeichert ist
4
6
... find(6) = find(2) = find(4) = 4
2
{ 2,4,6 }
Union-Operation
... mache die Wurzel das Baums für die Menge o2
zum Sohn der Wurzel des Baums für die Menge o1
4
6
1
2
4
3
6
{ 2,4,6 } ∪ { 1,3 } = { 1,2,3,4,6 }
4/6, Folie 21
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
1
2
3
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Implementierung von Union-Find-Strukturen (/* Version 1 */)
... verwenden ein eindimensionales Array zur Repräsentation aller Bäume
Väter
1
2
3
4
5
6
7
1
2
4
1
5
5
7
zugehörige Mengen:
4/6, Folie 22
© 2014 Prof. Steffen Lange
-
HDa/FbI
{ 1,3,4 }
{2}
{ 5,6 }
{7}
-
Datenstrukturen
Objekte
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Implementierung von Union-Find-Strukturen (/* Version 1 */)
4/6, Folie 23
Initialisierung
for ( int o = 1; o <= n; ++o )
v[o] = o;
... in Zeit O(n)
Union-Operation
void union ( int o1, int o2 ) {
v[o2] = o1;
}
... in Zeit O(1)
Find-Operation
int find ( int o ) {
while ( v[o] != o ) {
o = v[o];
}
return(o);
}
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
... in Zeit O(n)
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Implementierung von Union-Find-Strukturen (/* Version 2 */)
... verwenden zwei eindimensionale Arrays zur Repräsentation aller Bäume
1
2
3
4
5
6
7
Väter
1
2
4
1
5
5
7
Mächtigkeit
der Mengen
3
1
1
2
2
1
1
zugehörige Mengen:
4/6, Folie 24
© 2014 Prof. Steffen Lange
-
{ 1,3,4 }
{2}
{ 5,6 }
{7}
HDa/FbI
-
Datenstrukturen
Objekte
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Implementierung von Union-Find-Strukturen (/* Version 2 */)
for ( int o = 1; o <= n; ++o ) {
v[o] = o; m[o] = 1;
}
Initialisierung
void union ( int o1, int o2 ) {
if ( m[o1] > m[o2] ) {
v[o2] = o1;
m[o1] = m[o1] + m[o2];
}
else {
v[o1] = o2;
m[o2] = m[o2] + m[o1];
}
}
Union-Operation
4/6, Folie 25
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
... in Zeit O(1)
... aber, in
Zeit O(log(n))
... wie gehabt
Find-Operation
... in Zeit O(n)
Datenstrukturen
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Begründung – Laufzeit der Find-Operation (/* Version 2 */)
• 
für einelementige Mengen gilt: tiefe(B) ≤ log(n)
• 
es seien M1, M2 Mengen mit n1 bzw. n2 Elementen, wobei n1 ≥ n2 gilt
(/* nach IV gilt für die zugehörigen Bäume B1 und B2:
tiefe(B1) ≤ log(n1) und tiefe(B2) ≤ log(n2) */)
Fall 1:
tiefe(B) = tiefe(B1)
à log(n) = log(n1 + n2) ≥ log(n1) ≥ tiefe(B1)
B
B1
B1
B
2
4/6, Folie 26
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
2
Kapitel 4: Bäume / Graphen
Union-Find-Strukturen
u  Begründung – Laufzeit der Find-Operation (/* Version 2 */)
• 
für einelementige Mengen gilt: tiefe(B) ≤ log(n)
• 
es seien M1, M2 Mengen mit n1 bzw. n2 Elementen, wobei n1 ≥ n2 gilt
(/* nach IV gilt für die zugehörigen Bäume B1 und B2:
tiefe(B1) ≤ log(n1) und tiefe(B2) ≤ log(n2) */)
Fall 2:
tiefe(B) = tiefe(B2) + 1
à log(n) = log(n1 + n2) ≥ log(2n2) ≥ log(2) + log(n2) ≥ 1 + tiefe(B2)
B1
B1
4/6, Folie 27
© 2014 Prof. Steffen Lange
-
B
B
2
2
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen minimal aufspannender Bäume
u  Datenstruktur
• 
• 
4/6, Folie 28
eine Menge M von Kanten (/* dient zur Verwaltung der potentiell
aufzunehmenden Kanten */)
eine Union-Find-Struktur (/* Version 2 */) zur Verwaltung der Knotenmengen, der sukzessive erzeugten kreisfreien zusammenhängenden
Teilgraphen
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen minimal aufspannender Bäume
u  verfeinerte algorithmische Idee (/* mit Union-Find-Struktur */)
(1)  setze M = E, setze E‘ = ∅ und initialisiere eine Union-Find-Struktur für
die Knotenmenge V
(2)  solange E‘ < | V | - 1
a)  wähle eine Kante e = { x,y } aus M und streiche e aus M
b)  bestimme a = find(x) und b = find(y)
c)  teste, ob a ≠ b gilt
• 
• 
falls ja, so setze E‘ = E‘ ∪ { e } und führe die Operation
union(a,b) aus
falls nein, so ändere E‘ nicht
... geht in Zeit O(n) + m*O(1) + m*O(log(n)) (/* falls Variante 2 zur Implementierung von Union-Find-Strukturen verwendet wird */), wobei n die Anzahl der
Knoten von G und m die Anzahl der Kanten von G ist
4/6, Folie 29
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen minimal aufspannender Bäume
u  Illustration
B
A
B
C
D
E
A
B
C
D
E
1
1
1
1
1
A
C
M = { { A,B },{ A,C },{ B,C },{ A,D }, ... }
E‘ = ∅
D
A
B
C
D
E
A
A
C
D
E
2
1
1
1
1
M = { { A,C },{ B,C },{ A,D }, ... }
E‘ = { { A,B } }
4/6, Folie 30
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
E
Kapitel 4: Bäume / Graphen
Bestimmen minimal aufspannender Bäume
u  Illustration
B
A
B
C
D
E
A
A
C
D
E
2
1
1
1
1
A
C
M = { { A,C },{ B,C },{ A,D }, ... }
E‘ = { { A,B } }
D
A
B
C
D
E
A
A
A
D
E
3
1
1
1
1
M = { { B,C },{ A,D }, ... }
E‘ = { { A,B },{ A,C } }
4/6, Folie 31
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
E
Kapitel 4: Bäume / Graphen
Bestimmen minimal aufspannender Bäume
u  Illustration
B
A
B
C
D
E
A
A
A
D
E
3
1
1
1
1
A
C
M = { { B,C },{ A,D }, ... }
E‘ = { { A,B },{ A,C } }
D
A
B
C
D
E
A
A
A
D
E
3
1
1
1
1
M = { { A,D }, ... }
E‘ = { { A,B },{ A,C } }
4/6, Folie 32
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
E
Kapitel 4: Bäume / Graphen
Bestimmen minimal aufspannender Bäume
u  Grundbegriffe
• 
• 
es sei G = (V,E) ein ungerichteter Graph
es sei g(.) eine Funktion, die jeder Kante in V eine reelle Zahl zuordnet
... das Paar (G,g(.)) heißt ungerichteter kantengewichteter Graph
• 
4/6, Folie 33
das Gewicht g(G) von G ist die Summe der Gewichte der Kanten von G
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen minimal aufspannender Bäume
u  Aufgabenstellung
4/6, Folie 34
Eingabe:
ein ungerichteter zusammenhängender Graph G = (V,E)
und eine zugehörige Gewichtsfunktion g(.)
Ausgabe:
ein aufspannender Baum G‘ = (V‘,E‘) in G, der ein
minimales Gewicht hat
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen minimal aufspannender Bäume
u  Datenstruktur
• 
• 
4/6, Folie 35
eine Menge M von Kanten (/* dient zur Verwaltung der in G‘ potentiell
aufzunehmenden Kanten */)
eine Union-Find-Struktur (/* Version 2 */) zur Verwaltung der Knotenmengen, der sukzessive erzeugten kreisfreien zusammenhängenden
Teilgraphen
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmen minimal aufspannender Bäume
u  algorithmische Idee
(1)  setze M = E, setze E‘ = ∅ und initialisiere eine Union-Find-Struktur für
die Knotenmenge V
(2)  solange E‘ < | V | - 1
a)  wähle eine Kante e = { x,y } mit minimalem Gewicht aus M und
streiche e aus M
b)  bestimme a = find(x) und b = find(y)
c)  teste, ob a ≠ b gilt
• 
• 
falls ja, so setze E‘ = E‘ ∪ { e } und führe die Operation
union(a,b) aus
falls nein, so ändere E‘ nicht
... geht in Zeit O(n) + m*O(m)+ m*O(log(n)) (/* falls Variante 2 zur Implementierung von Union-Find-Strukturen verwendet wird */), wobei n die Anzahl der
Knoten von G und m die Anzahl der Kanten von G ist
4/6, Folie 36
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Kapitel 4: Bäume / Graphen
Bestimmung minimal aufspannender Bäume
u  Anmerkung
• 
falls man die Menge M, der aufzunehmenden Kanten, mit Hilfe einer
Prioritätswarteschlange realisiert (/* Heap, wobei statt „≥“ ein „≤“ zur
Sicherstellung der Heap-Eigenschaft verwendet wird */), kann 2a)
jeweils in Zeit O(log(m)) realisiert werden, wobei m die Anzahl der
Kanten von G ist (/* die Initialisierung der Prioritätswarteschlange
kostet einmalig Zeit O(m) */)
... geht offenbar in Zeit O(n) + O(m) + m*O(log(m)) + m*O(log(n)),
wobei n die Anzahl der Knoten von G und m die Anzahl der Kanten von
G ist
4/6, Folie 37
© 2014 Prof. Steffen Lange
-
HDa/FbI
-
Datenstrukturen
Herunterladen