Grundlagen der Programmierung 2 Bäume

Werbung
Grundlagen der Programmierung 2
Bäume
Prof. Dr. Manfred Schmidt-Schauÿ
Künstliche Intelligenz und Softwaretechnologie
15. Mai 2007
Datenstruktur Baum
Binäre, geordnete Bäume in Haskell:
data Binbaum a = Bblatt
•
•
•
•
a | Bknoten (Binbaum a) (Binbaum a)
Daten (Markierungen) sind an den Blättern des Baumes
Die Daten sind von gleichem Typ
Jeder (innere) Knoten hat genau zwei Tochterknoten
es gibt linken und rechten Tochterknoten (geordnet)
Grundlagen der Programmierung 2
- 1 -
Datenstruktur Baum; Beispiel
Der folgende binäre Baum
1
~~
~~
~
~~
~ ~
·
ii
iiii
i
i
i
iiii
iiii
i
i
i
ii
tiiii
>>
>>
>>
>>
>>
<
<<<
<<
<<
<
3
·
· ???
7
??
??
??
· >>>
>>
>>
>>
8
4
hat eine Darstellung als
Bknoten (Bknoten (Bblatt 1)
(Bknoten (Bblatt 3) (Bblatt 4)))
(Bknoten (Bblatt 7) (Bblatt 8))
Grundlagen der Programmierung 2
- 2 -
Einige Verarbeitungsfunktionen
Rand: Liste der Markierungen der Blätter:
b_rand (Bblatt x)
= [x]
b_rand (Bknoten bl br) = (b_rand bl)
++ (b_rand br)
testet, ob eine Markierung existiert:
b_in x (Bblatt y)
= (x == y)
b_in x (Bknoten bl br) = b_in x bl
||
b_in x br
wendet eine Funktion auf alle Elemente des Baumes an,
Resultat: Baum der Resultate
b_map f (Bblatt x)
= Bblatt (f x)
b_map f (Bknoten bl br) =
Bknoten (b_map f bl)
Grundlagen der Programmierung 2
(b_map f br)
- 3 -
Einige Verarbeitungsfunktionen (2)
Größe des Baumes:
b_size (Bblatt x)
=
b_size (Bknoten bl br) =
1
1+ (b_size bl) + (b_size br)
Summe aller Blätter, falls Zahlen:
b_sum (Bblatt x)
= x
b_sum (Bknoten bl br) = (b_sum bl) + (b_sum br)
Tiefe des Baumes:
b_depth (Bblatt x) = 0
b_depth (Bknoten bl br) =
1 + (max (b_depth bl) (b_depth br))
Grundlagen der Programmierung 2
- 4 -
Einige Verarbeitungsfunktionen (3)
schnelles fold über binäre Bäume:
foldbt :: (a -> b -> b) -> b -> Binbaum a -> b
foldbt op a (Bblatt x)
= op x a
foldbt op a (Bknoten x y) = (foldbt op (foldbt op a y) x)
foldbt mit optimiertem Stackverbrauch:
foldbt’ :: (a -> b -> b) -> b -> Binbaum a -> b
foldbt’ op a (Bblatt x)
= op x a
foldbt’ op a (Bknoten x y) = (((foldbt’ op) $! (foldbt’ op a y)) x)
effizientere Version von b rand und b sum
b_rand_eff = foldbt (:) []
b_baum_sum’ = foldbt’ (+) 0
Grundlagen der Programmierung 2
- 5 -
Auswertung mit foldbt
Werte foldbt (+) 0 "(((1,2),3),(4 ,5))" aus:
syntaktisch richtiger Aufruf:
foldbts (+) 0 (Bk (Bk (Bk (Bb 1) (Bb 2)) (Bb 3)) (Bk (Bb 4) (Bb 5)))
foldbt (+) 0 "(((1,2),3),(4 ,5))"
--> foldbt (+) (foldbt (+) 0 "(4,5)")
"((1,2),3)"
--> foldbt (+) (foldbt (+) (foldbt (+) 0 (5)) (4)
"((1,2),3)")
-->
-->
-->
-->
-->
-->
-->
foldbt
foldbt
foldbt
foldbt
foldbt
foldbt
1+ (2+
(+)
(+)
(+)
(+)
(+)
(+)
(3+
(foldbt (+) (5+0) (4)
"((1,2),3)")
(4+ (5+0))
((1,2),3)
(foldbt (+) (4+ (5+0))
(3)) "(1,2)"
(3+ (4+ (5+0)))
(1,2)
(foldbt (+) (3+ (4+ (5+0))) (2) (1))
(2+ (3+ (4+ (5+0)))) (1)
(4+ (5+0))))
(Der Baum ist auf dieser Folie vereinfacht dargestellt)
Grundlagen der Programmierung 2
- 6 -
Bemerkungen zu foldbt
Sei tr binärer Baum mit Randliste [a1, . . . , an]
(foldbt f a tr) entspricht (f a_1
(f a_2 (... (f a_n a) ...s))).
D.h. foldbt entspricht foldr
Grundlagen der Programmierung 2
- 7 -
Suchbaum
Effizienzsteigerung beim Zugriff auf Elemente:
sortierte Liste als Baum
Jeder Knoten enthält als Markierung den größten Schlüssel des linken
Teilbaumes mit den kleineren Werten.
Laufzeit des Zugriffs: logarithmisch in der Anzahl der Elemente
Grundlagen der Programmierung 2
- 8 -
Suchbaum, Beispiel
1












1
3
Grundlagen der Programmierung 2
jj
jjjj
j
j
j
jjj
jjjj
j
j
j
jjj
jjjj
j
j
j
jjjj
jjjj
j
j
j
tjjjj
??
??
??
??
??
??
??
??
?










 
3 ???
??
??
??
??
??
??
??
5 ???
??
??
??
??
??
??
??
7










 
7 AAA
AA
AA
AA
AA
AA
AA
AA
A
11
5
- 9 -
Haskell-Implementierung: Suchbaum
data Satz a
= Satz Integer
a
data Suchbaum a =
Sblatt Int a
| Sknoten (Suchbaum a) Int (Suchbaum a)
| Suchbaumleer
Verwendung:
Suchbaum (Satz a)
intial = Suchbaumleer
Grundlagen der Programmierung 2
- 10 -
Haskell-Implementierung: Suchbaum
einfuegeDbS (Satz x sx) Suchbaumleer = Sblatt x (Satz x sx)
einfuegeDbS (Satz x sx) (Sblatt k satzk) =
if x < k
then Sknoten (Sblatt x (Satz x sx)) x (Sblatt k satzk)
else if x == k then error " schon eingetragen"
else Sknoten (Sblatt k satzk) k (Sblatt x (Satz x sx))
einfuegeDbS (Satz x sx) (Sknoten l k r) =
if x < k then Sknoten (einfuegeDbS (Satz x sx) l) k r
else if x == k then error " schon eingetragen"
else Sknoten l k (einfuegeDbS (Satz x sx) r)
Grundlagen der Programmierung 2
- 11 -
Haskell-Implementierung zum Suchbaum
Elementweises Einfügen :
sortiert die Eingabe
Vorsicht:
Der entstehende Baum kann
unbalanciert sein!
bewirkt Verschlechterung der Laufzeit
von O(log (n)) auf O(n)
Abhilfe:
Balancieren des Baumes durch Rotationen
Laufzeit des Baumaufbaus
mit Balancieren:
O(n ∗ log (n))
Grundlagen der Programmierung 2
- 12 -
Allgemeinere Bäume
mit beliebiger Anzahl Töchter
Die Programmierung ist analog zu einfachen Bäumen
data Nbaum a = Nblatt a | Nknoten [Nbaum a]
nbaumrand :: Nbaum a -> [a]
nbaumrand
(Nblatt x) = [x]
nbaumrand
(Nknoten xs) = concatMap nbaumrand xs
Grundlagen der Programmierung 2
- 13 -
Herunterladen