03 Basic Data Structures
03 Basic Data Structures
03
Basic Data Structures
Stack-Operationen
Datenstruktur („wie“) als Array
oder verkettete Liste
isEmpty(S) - -
gibt an, ob Stack S leer
push(S,k) - schreibt&
k als neues oberstes Element auf Stack o
-
S
(bzw. Fehlermeldung, wenn Stack voll) -
push(S,k) pop(S)
(3) …
Fokus dieses Teils der Vorlesung liegt auf Entwurf der Datenstrukturen;
alle Lösungen erfüllen „natürliche“ Forderungen an solche Operationen.
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 5
Beispiel: Bitcoin
scriptPubKey:
OP_DUP OP_HASH160 56fa64a8bd7852d2c58095fa9a2fcd52d2c580b65d35549d
OP_EQUALVERIFY OP_CHECKSIG
56fa64a8…
PK Hash(PK) Hash(PK)
PK PK PK PK PK
0 1 2 3 4 5 6 7 8
S 12 47 17 98 72
[Link]
pop() zeigt auf oberstes Element
0 1 2 3 4 5 6 7 8
S 12 47 17 98
[Link]
bewegt sich eine Position nach links
gibt 72 zurück
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 7
Stacks als Array (II) Annahme: maximale Größe MAX
des Stacks vorher bekannt
0 1 2 3 4 5 6 7 8
S 12 47 17 98
[Link]
push(9)
0 1 2 3 4 5 6 7 8
S 12 47 17 98 9
[Link]
bewegt sich eine Position nach rechts
S 12 47 17 98 9
pop(S) push(S,k)
1 IF isEmpty(S) THEN
-
1 IF [Link]==MAX-1 THEN
- -
2 error-‘underflow‘ 2 error -
‘overflow‘
3 ELSE 3 ELSE
4 [Link]=[Link]-1; 4 [Link]=[Link]+1;
-
-
-
5 return -
S.A[[Link]+1]; 5 S.A[[Link]]=k;
-
S 12 47 17 98 9 13 45 7 33
[Link]
push(14)
-
zusammenhängendes Array um, ( Datenstruktur verkette Listen)
12 47 17 98 9 13 45
push(7)
Kopiere
12 47 17 98 9 13 45 7
Kopiere push(33)
12 47 17 98 9 13 45 7 33
Kopiere push(34)
12 47 17 98 9 13 45 7 33 34
In Summe also
𝑛 Kopier-Schritte 1 ①
𝑛 + ∑ gü 𝑖 = Ω(𝑛 )
Y Kopier-Schritte
-
𝑛 + 1 Kopier-Schritte 2
Somit durchschnittlich
&
Ω 𝑛 Kopier-Schritte
-
②
pro Push-Befehl!
… -
n n Push befehl
.
n
-2 (n) =
R(n))
2𝑛 − 2 Kopier-Schritte
2𝑛 − 1 Kopier-Schritte
⑰
-
---
Gesucht: Lösung, die maximal jeweils O(#𝐸𝑙𝑒𝑚𝑒𝑛𝑡𝑒) Zellen benötigt
Push
-Befehle
-
Schrumpfe und kopiere um, sofern weniger als ein Viertel belegt
-
⑧ --
-
2 [Link]=-1; -
2 return true
-
3 [Link]=1;
-
3 ELSE
4 return false;
8 return S.A[[Link]+1]; ↓
rerdoppele Speicher und
Kopie um
Speicher
halbite
&
5 RESIZE(S.A,[Link]); push
top=3
+
-1 2 p 1
2 memsize=8
3-5
pop(S)
pop
1-4 top=2
&
1 IF isEmpty(S) THEN
2 error ‘underflow‘
3
4
ELSE
[Link]=[Link]-1; wil
Arrag Trageg pop (8)
1-4 top=1
5 >
-
IF 4*([Link]+1)==[Link] THEN
6 [Link]=[Link]/2; memsize=4
7 RESIZE(S.A,[Link]); 5-7
8 return S.A[[Link]+1];
(8)
& imedt
(1) 𝑛 Elemente (unmittelbar
nach letzter Vergrößerung) (2) neue Speichergrenze wird nur erreicht,
wenn dann mindestens 𝑛 viele Push-Befehle
-
-
(3) Umkopieren kostet dann O(𝑛) Schritte
Quelle: Wikipedia
5 12 17 47 72 98
head
zeigt auf
erstes Element
(bzw. ist nil für
3 Jedes Element x besteht aus:
key – Wert (hie( +* )
prev – Zeiger auf Vorgänger (bzw. nil)
leere Liste) next – Zeiger auf Nachfolger (bzw. nil)
[Link]=6 13
12
A
LED
0 1 2 3 4 5 6 7 8
12 6 nil 45 nil 0
45 12
-
search(L,k) -
//returns pointer to k in L (or nil)
short circuit
evaluation
1 current=[Link]; (wie in Java)
Search(L,17)
Laufzeit= (n)
head 2/3 2/3
1
#
nur
einneh
5 12 17 47 durchlaufen
1 2/3
2/3 2/3 2/3 nil
Search(L,18)
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 22
Elementare Operationen auf verketteten Listen
insert(L,x) //inserts element x in L call-by-reference
-
-
bzw. call-by-value
1 [Link]=[Link]; - für Objekte wie in Java
Anfang
am -
2 [Link]=nil;
de
3 IF [Link] != nil THEN Liste
4
5
[Link]=x;
[Link]=x;
einfügen Laufzeit= (1)
5 Insert(L,x)
head
2 1
37 5 12 17 47
3/4
e
Wenn zuerst Suche nach Wert, dann wiederum Laufzeit (n)! ⑧
x head
37 5 12 37 47
5
head Insert(L,x)
2 1
37 5 12 37 47
3/4
Ell
2 & [Link]=[Link]
Achtung: Löschen
⑭
3 ELSE
eines Wertes k
4 [Link]=[Link];
kostet Zeit①
(n)
5 IF [Link] != nil THEN - -
6 [Link]=[Link];
e wenn zu lischende
Element
gefunden werden
soll, dann Zeit)
5/6
head O
x
Delete(L,x)
C >
5 12 17 47
-
1/2
-
Spezialfälle für
3 ELSE
4 [Link]=[Link]; Listenanfang/-ende
5 IF [Link] != nil THEN
6 [Link]=[Link];
Sentinel
[Link] head =[Link]
nil 5 12 17 47
Sentinel ist „von außen“ nicht sichtbar Leere Liste besteht nur aus Sentinel
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 26
Löschen mit Sentinels
Sentinel
Delete(L,x)
[Link] head =[Link] x
nil 5 12 17 47
1/2
&
cikar.
enqueue(Q,k) - schreibtO
k als neues hinterstes Element aufO
-
Q
(bzw. Fehlermeldung, wenn Queue voll)
Queue Q
enqueue(Q,k) dequeue(Q)
①
(FIFO – first in, first out) rear front
0 1 2 3 4 5 6 7
Q 17 98 9 23 37 8 47
[Link] [Link]
Problem:
Selbst wenn maximale Anzahl Elemente, die gleichzeitig in der Queue sind,
vorher bekannt, kann --
-
0 1 2 3 4 5 6 7
Q 47 8 37 23 9 98 17
[Link] [Link]
Problem:
Selbst wenn Array nach rechts unendlich lang,
wird Speicher links von [Link] verschwendet
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 31
MAX Elemente
Queues als (virtuelles) zyklisches Array gleichzeitig in Queue
[Link] 0 1
wandert zyklisch
nach rechts beim 7 2
Auswerfen
nur virtuell
6 3
0 1 2 3 4 5 6 7
47 8 37 23 9 98 17 real
Modulo-Operator
Der Modulo-Operator 𝑥 𝑚𝑜𝑑 𝑛 bildet eine ganze Zahl 𝑥 auf die Zahl 𝑦
zwischen 0 und 𝑛 − 1 ab, so dass 𝑦 = 𝑥 − 𝑖 𝑛 für eine ganze Zahl 𝑖.
Achtung: In Java ist der %-Operator als Divisionsrest für negative Zahlen 𝑥
anders definiert, dort ist z.B. −4 % 7 = −4. Man kann dies unter Beachtung
eventueller Überläufe abbilden durch 𝑥 𝑚𝑜𝑑 𝑛 = ((𝑥 % 𝑛) + 𝑛 ) % 𝑛.
7 2
6 3
5 4
dequeue(Q) enqueue(Q,k)
f
O ↑
9
1 IF isEmpty(Q) THEN 1 IF [Link]==[Link] AND ![Link]
-
↑
Queue W
3 ELSE S 10 16 3 ELSE
4 [Link]=[Link]+1 mod MAX; 4 Q.A[[Link]]=k;
5 IF [Link]==[Link] THEN 5 [Link]=[Link]+1 mod MAX;
6 [Link]=true; 6 [Link]=false;
7 return Q.A[[Link]-1 mod MAX];
5 12 17 47 72 98
front rear
isEmpty(Q)
new(Q)
1 IF [Link]==nil THEN
1 [Link]=nil;
2 return true
2 [Link]=nil;
3 ELSE
4 return false;
dequeue(Q) enqueue(Q,x)
Song
5 [Link]=[Link]; 11
-
5 [Link]=nil; aix
-
sen eleve
1j4 göste sağle
>
6 return x; 6 [Link]=x; -
Stack Queue
Verkettete Liste
Operation Laufzeit*
Einfügen (1)
Löschen
Suchen
es(1)
(n)
Laufzeit Löschen
eines Wertes (n)
Verkettete Liste
Operation Laufzeit*
Einfügen (1)
Löschen (1)
Suchen (n) Geht das besser?
23 17 23 23
9 12 15
23 17 23 23
wunzel
5 5
9 12 9 12
23 17 23 23 17 23
5 5
als Baum
verschieden
9 12 9 12
17 23 23 23 17 23
Geschwister/ Nachkomme/
23 17 23 ~ 2
siblings of… ~ descendant of …
Blatt/leaf ~
T -
Höhe des Baumes/ tree height
= maximale Tiefe eines Knoten
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 45
Begrifflichkeiten (II) A =
Binärbaum:
jeder Knoten hat maximal zwei Kinder,
left=child[0] und right=child[1]
… oder …
d.h. Ausgangsgrad/outdegree
rechts
⑬
-
markiere Knoten
auch graphisch
Halbblatt 12 als linkes oder
9 -
23 17 23 Höhe leerer
-
-
Baum hier per
Konvention&-1
(linker) Teilbaum von z (rechter) Teilbaum von z
Ein
bspw -
krofen Baum :
O
er I
>
↓
----
er =
Höhe
per
der Teilbare
bencention = -1
-
-
1 + 1
Also
gegarthöle = max ( - 1
,
-
13 + 1 = -
= 0
Gesamtbil
-
3-131
+=c,
linze teilburn-Vater-rechter teilbaum
Trit
Beispielanwendung:
Inorder-Traversieren von Binärbäumen
Serialisierung
..
aga *
23 inorder(x)
D 1 IF x != nil THEN
2 inorder([Link]);
3 print [Link];
17 24 4 inorder([Link]);
I
Bei Bedarf mit „Wrapper“
inorderTree(T)=inorder([Link])
9 23 25
I
inorder([Link]) ergibt
, 17
9 , 23 ,
23 ,
24 25,
r
9 17 23 23 24 25
23 inorder(x)
1 IF x != nil THEN
2 inorder([Link]);
3 print [Link];
17 24 4 inorder([Link]);
S
23 0
-- 17 0 .
Siehe
#
E
17 24 1 vs. 1 9 -
-
23
& 9 23 25 2 2 - - - - 23 - 25
Blatt
-
----- 24
Verschiedene Bäume, aber gleiche Inorder
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 49
>
- Saga citgi
Pre- und Postorder-Traversieren von Binärbäumen (I)
↓
wi
Sola -
preorder(x)
City ; 23 -
1 IF x != nil THEN
2 print [Link];
3 preorder([Link]);
4 preorder([Link]);
-
17
-
-
&
24 -
3 ,
17
,
9, 23 , 24 25
,
-
9 - -
23 -
&
25 -
Bost
9 23 17 25 24
, ,
, , , 23
preorder([Link]) ergibt
23 17 9 23 24 25
O
preorder(x)
23
1 IF x != nil THEN
2 print [Link];
3 preorder([Link]);
4 preorder([Link]);
17 24
postorder(x)
1 IF x != nil THEN
9 23 25 2 postorder([Link]);
3 postorder([Link]);
4 print [Link];
Se
a
preorder([Link]) ergibt postorder([Link]) ergibt
O 23 17 9 23 24 25 9 23 17 25 24
⑧
23
6 3
23
Zeiger auf rechten Teilbaum
noch vorhanden, wenn
linker Teilbaum bereits
gelöscht wurde
23 23
17 24 vs. 17
9 22 25 9 24
22 25
Preorder = 23 17 9 29 24 25
⑨
17 9 29
a
24 25
-
(1) Identifiziert Wurzel
Pre =O
17 9 29 Pre = 24 25
In = 9 17 29 In = 24 25
Inorder = 9 17 29 23 24 25
Bilde Teilbäume rekursiv
(2) Identifiziert Werte im
linken und rechten Teilbaum
Gilt analog für Postorder - Postomer hat wer zel
als letztes
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 56
Inorder und eindeutige Werte sind notwendig
23 23
Haben gleiche
Pre-, Post- und Inorder
vs.
23 23
23 23
Haben gleiche
Pre- und Postorder
vs.
17 17
mit wie
2) 1
441
T
-
man
,
Fortschritt manef
Basis
S 2+ 1 will kne ling /
nkv
Inne Teilbaur gelese
rechter Teilbar
-
17 12
9
9 23 25
⑤
Laufzeit = Θ(𝑛)
Einfügen um ·
vor zu
insert(T,x) einfügend
Kate
in
8
//[Link]==[Link]==[Link]==nil;wurd
4 [Link] x
1-3
1 IF [Link] != nil THEN
2 [Link]=x;
3 [Link]=[Link];
[Link] 23 4 [Link]=x;
17 12
Laufzeit = Θ(1)
9 23 25
*Achtung: erzeugt-
linkslastigen Baum!!!
T
Halbblatt ist selbst x oder Wurzel
Idee:
Ersetze x durch Halbblatt ganz rechts
[Link] [Link] 23
23
9
17
23
x
4 12
25 9
25
23
12
0
connect(T,y,w)
//connects w to [Link]
v loschade
Er
1 v=[Link];
↑ 2 IF y != [Link] THEN // y pretk null
y 3 IF y == [Link] THEN /right child
[Link] 4+10 4 [Link]=w;
5 ELSE "Reft child
6 [Link]=w;
7 ELSE
y w 8 [Link]=w;
8+10
↓
habblatt
9 IF w != nil THEN
eur
10 [Link]=v;
w
(w muss dabei nicht an y hängen)
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 63
delete(T,x) //assumes x in T
Löschen: Algorithmus
1 y=[Link];
finden 4) -
um zu 2 WHILE [Link]!=nil DO
welchen koten
en
3 y=[Link]; weil
&
2
-
L soll seme
[Link] 4 connect(T,y,[Link]); der nicht
23 left to prent set) learda-
ge y. Stehen
5 IF x != y THEN
57
1-3
6 [Link]=[Link];
7 IF [Link] != nil THEN
12 8 [Link]=y;
17 x
9 [Link]=[Link];
4 10 IF [Link] != nil THEN
11 [Link]=y;
12
9 23 25 12 connect(T,x,y);
y
to X
prent
6-11
y
Laufzeit = Θ(ℎ)
5-11) ist dafür da
, dass von die Kunden
Operation Laufzeit*
Einfügen (1)
Löschen (h)
Suchen (n) Geht das besser?
17 24
linke teilbaum
kleine
gleich
9 22 25 recht Teilbaum
Größer gleich
Binärer Suchbaum:
Binärbaum, so dass für alle Knoten z gilt:
WennOx Knoten im linken Teilbaum von z, dann [Link] <= [Link]
Wenn y Knoten im rechten Teilbaum von z, dann [Link] >= [Link]
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 66
--
Preorder + eindeutige Werte ⇒ Binärer Suchbaum
23
Li
(1) Identifiziert Wurzel
2
17
--
g 22 -
-
Preorder = 23 17 9 22 24 25
17 9 22 24 25
Pre = 17 9 22 Pre = 24 25
(2) Identifiziert Werte im
-
wurzel
Post
-
23 17
vs.
17 24 9 23
9 22 25 22 25
24
Element bleher
ist
17 24
O
5/6
Laufzeit = 𝑂(ℎ)
A
ℎ Höhe des Baumes
9 22 25
2
3 x=[Link]
Ticke
IF [Link] > k THEN linben in Heilbor ,
da be beleve als
X.
Sey ist
4 ELSE
5 x=[Link]; & suche rechten in /bare ,
do 2
guidegleich
6 return x; als
bey
X
ist
-
2 WHILE x != nil DO
3 px=x;
4 IF [Link] > [Link] THEN
5 x=[Link]
24
6 ELSE
xnil
px24 -
7 x=[Link];
8 [Link]=px;
8-15
9 IF px==nil THEN
-
z 22 25 10 -
[Link]=z
11 ELSE
12 IF [Link] > [Link] THEN
[Link]=z S
Eltern kote
13 als neue
größer
Krefe daher
,
kofe
neve
like Kind ist
14 ELSE
Laufzeit = 𝑂(ℎ) O 15 [Link]=z; Eltern Knote
>
-
neve
kleiner gleich as
brote , deher neue
* Ne ist rechter kind
nil r L R
Bedingung an Struktur/Werte
L R ② im BST bleibt erhalten
&
Löschen im BST (II) rechtes Kind von Knoten O
z hat kein linkes Kind
Dannnehme diese rechte
oder oder
und alle Seine
kind
z ersetze Zu
lischende r
mit den
Kote(2)
and von t
recure
l r l s
… …
nil s BST-Bedingung L R
bleibt erhalten
Kote
M
l r l r
… …
s Y s
y
BST-Bedingung
nil L R L R
Y bleibt erhalten
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 74
Löschen: Transplantation hängt TeilbaumO
v an Elternknoten von u
v zu löschen
um
x
transplant(T,u,v) Hänge
L V an
y parent ve v
,
asn't u leer
v
7 [Link]=v;
8 IF v != nil THEN verbinden
9 [Link]=[Link];( rit Y
elen von
O
Laufzeit = Θ(1)
J
1
z 1 IF [Link]==nil THEN Fol :
(
1-2 > maximal I -
2 transplant(T,z,[Link]) und
3 ELSE>
- linke orgette wit rahts
leer
-
,
ersetze
↑
8
4 IF [Link]==nil THEN it dieser ~
Kind
nil r 5 transplant(T,z,[Link])
ersetze mit lin
-rechte
her ,
6 ELSE
↓
7 y=[Link];
8 WHILE [Link] != nil DO y=[Link];
… …
9 IF [Link] != z THEN
10 transplant(T,y,[Link]);
11 [Link]=[Link];
12 [Link]=y;
13 transplant(T,z,y);
14 [Link]=[Link];
15 [Link]=y;
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 76
Löschen: Algorithmus (II)
delete(T,z)
1 innes
z
1 IF [Link]==nil THEN
")
7-8 i =
2 transplant(T,z,[Link]) Kind
3 ELSE
4 IF [Link]==nil THEN hat
3
Z
… kein
r 5 transplant(T,z,[Link])
rechtes
6 ELSE
king
7 y=[Link];
8 ⑨
WHILE [Link] != nil DO y=[Link];
finde
… Herste
y 10 transplant(T,y,[Link]); rechges
Z
11 [Link]=[Link];
9-10
12 [Link]=y;
13 transplant(T,z,y);
nil Y 14 [Link]=[Link];
15 [Link]=y;
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 77
Löschen: Algorithmus (III)
delete(T,z)
z
1 IF [Link]==nil THEN
2 transplant(T,z,[Link])
3 ELSE
… 4 IF [Link]==nil THEN
r 5 transplant(T,z,[Link])
11-12 6 ELSE
7 y=[Link];
8 WHILE [Link] != nil DO y=[Link];
8
…
9 IF =
[Link] != z THEN
19
y 10 transplant(T,y,[Link]);
11 [Link]=[Link];
12 - [Link]=y;
13 transplant(T,z,y);
nil Y 14 [Link]=[Link];
15 [Link]=y;
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 78
Löschen: Algorithmus (IV) Laufzeit = O(ℎ)
13
delete(T,z)
z y
1 IF [Link]==nil THEN
2 transplant(T,z,[Link])
3 ELSE
… 4 IF [Link]==nil THEN
14-15 5 transplant(T,z,[Link])
r
6 ELSE
7 y=[Link];
8 WHILE [Link] != nil DO y=[Link];
…
9 IF [Link] != z THEN
y 10 transplant(T,y,[Link]);
11 [Link]=[Link];
12 [Link]=y;
13 transplant(T,z,y);
nil Y 14 [Link]=[Link];
15 [Link]=y;
Algorithmen und Datenstrukturen | Marc Fischlin | SS 23 | 03 Basic Data Structures | 79
Höhe Laufzeit
besser, wenn
viele Such-Operationen
und ℎ klein relativ zu 𝑛
-
Best-Case: Worst-Case:
Laufzeit = 𝑂(log 𝑛) Laufzeit = (𝑛)
ℎ = 𝑂(log 𝑛) 23 9 ℎ =𝑛−1
17
17 34
22
9 22 27 35
35
1 T=newTree();
2 WHILE D != ∅ DO
3 Pick d uniformly from D;
4 insert(T,newNode(d));
5 remove d from D;
6 return T;
23
27 | Victor | CS | …
ID Name Department …
17 34
23 Bob CS …
17 Alice Math …
9 Eve CS …
9 22 27 22 Carol Physics …
34 Peggy Math …
Knoten speichert nur 27 Victor CS …
Primärschlüssel (hier ID)
und Zeiger auf Daten … … … …
22 | Carol | Physics | …
23
23 | Bob | CS | …
27 | Victor | CS | …
ID Name Department …
17 34
23 Bob CS …
17 Alice Math …
9 Eve CS …
9 22 27 22 Carol Physics …
34 Peggy Math …
27 Victor CS …
… … … …
23
Alice Eve Victor
ID Name Department …
17 34
23 Bob CS …
17 Alice Math …
9 Eve CS …
9 22 27 22 Carol Physics …
34 Peggy Math …
27 Victor CS …
Zusätzliche Indizes kosten Speicherplatz,
daher nur sinnvoll, wenn oft gesucht wird … … … …
left
X-right ! EnilDo
-
-
-
if
=
t
t retun XI
return Troo
X
=
T .
vo
a
ein mehr +
Füge , ver
.
2 ,
-
a(n)