Bei den Maxiphobic Heaps wurde bereits das Optimale an Leifzeitverhalten aus
den Binary Heap Trees herausgeholt, was möglich ist. Allerdings ist die
join Funktion doch recht aufwendig geraten, so dass man überlegen kann,
ob es nicht auch einfacher geht. Also ohne zu Zählen.
Man kann sich da das Verfahren zu Nutze machen, das in der Regel beim Kartengeben
in Kartenspiele angewendet wird. Auch hier könnte man sich aufwendig merken,
wer bereits wie viele Karten bekommen hat und immer demjenigen eine Karte geben,
der die wenigsten bereits bekommen hat. Es geht aber einfacher: Man verteilt
die Karten einfach reih um. Und muss sich nur noch merken, wer als letztes eine
Karte bekommen hat.
Das übertragen wir jetzt auf die join Funktion. Dazu bekommt jeder Ast
eine "Farbe" zugeteilt, wobei in der Wurzel mitgespeichert wird, welcher
Ast als nächstes an der Reihe ist, zusammengeführt zu werden. Der
linke Ast ist in diesem Fall blau und der rechte rot. Des weiteren gilt für
einen neu erzeugten Baum, dass zunächst der linke Ast bearbeitet wird.
Also bekommt ein neuer Baum die Farbe Blau.
Die geänderte Definition und die neuen Funktionen sehen danach folgendermassen
aus:
Data Color =
Blau | Rot Data (Ord a) => Tree a = Null | Fork Color a (Tree a) (Tree a) |
isEmpty :: (Ord a) => Tree a ->
Tree a |
minElem :: (Ord a) => Tree a ->
a minElem (Fork c x a b) = x |
deleteMin :: (Ord a) => Tree a -> Tree a deleteMin (Fork c x a b) = merge a b |
insert :: (Ord a) => a ->
Tree a -> Tree a insert x a = merge (Fork Blau y Null Null) a |
merge :: (Ord a) =>
Tree a -> Tree a -> Tree a |
join :: (Ord a) =>
Tree a -> Tree a -> Tree a |
Dieses Verfahren ist schon sehr einfach gehalten. Aber geht es nicht noch ein
wenig einfacher? Man könnte die beiden Äste als Teil eines FIFOs betrachten,
in den sie nach der Bearbeitung immer wieder hineingegeben werden, so dass sich
eine abwechselnde Bearbeitung ergibt. Auf diesem Wege könnte man sich den
Umweg über die Farben sparen. Und genau diesen FIFO haben wir zumindest
teilweise bereits mit unserer Baumstruktur definiert.
Der linke Ast wird dabei als derjenige definert, der in dem FIFO als nächstes
an der Reihe ist "gemerged" zu werden. Wurde diese Operation ausgeführt,
so tascht er mit dem rechten Ast die Plätze, womit der Inhalt dieses Astes
als nächstes dran wäre. Der Vorteil an diesem Verfahren ist, dass
die ursprüngliche Definition der Binary Heap Trees beibehalten werden kann
und wir jetzt eine Antwort darauf haben, welches der sechs Verfahren aus dem
ersten Kapitel das optimalste ist:
join (Fork x a b) c = Fork x b (merge a c) |