Binäre Suchbäume

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

Eingeproggt

Betreff: Binäre Suchbäume

BeitragMo, Apr 12, 2010 0:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Servus, grüß euch und herzlich willkommen!

Musste für die Uni mich mit binären Suchbäumen auseinander setzen und da in meinen Unterlagen so schöne Pseudo-Codes enthalten sind hab ich sie gleich in BB-Syntax umgesetzt. Smile

Dank dem Hinweis von mpmxyz ist der Code sowohl für numerische als auch für alphanumerische Schlüssel verwendbar, ein Nachteil bleibt aber noch:
Arrow Der Baum ist nicht "balanciert", das heißt wenn man eine geordnete Reihenfolge an Elementen hinzu fügt so würden die alle hintereinander aufgelistet werden - es würde eine Liste entstehen und keine Baumstruktur - Die ganze Arbeit ist umsonst denn Types sind ja bekanntermaßen bereits Listen...
NACHTRAG am 1.5.2010:
Unser Forum-Mitglied darth hatte dieselbe Vorlesung wie ich und ähnliche Lust auf diese binären Bäume wie ich nur dass er es bis zum balancierten Baum durchgezogen hat - Super darth Wink
Ich verweise an dieser Stelle einfach auf seinen Worklog in welchem er seine Arbeit beschreibt und auch vorstellt:
--> https://www.blitzforum.de/worklogs/292/#2342

Also wenn man den Type ergänzt bzw. wie im Kommentar angegeben den Type per "Alle ersetzen" umbenennt funktioniert das Prinzip wunderbar, auch für eigene Anwendungen - in meinem Beispielcode schaff ich 10.000 Suchvorgänge in einem Baum mit 10.000 Elementen in 26ms, ohne DebugMode sogar in 6ms. Also ich find das geil Cool

Also hier der Code / die Lib / das Include:

BlitzBasic: [AUSKLAPPEN]
;Binärer Suchbaum, BB-Vorlage
;von Christoph Mach, April 2010
;Lizenz: WTFPL (http://sam.zoy.org/wtfpl/)

Type node ;Umbenennen wäre möglich durch die Funktion "Alle ersetzen" deines jeweils verwendeten Programmeditors
Field parent.node
Field Left.node
Field Right.node
Field key$ ;ACHTUNG: Will man wirklich nur Zahlen verwenden, so ist key% deutlich schneller! (Faktor ~100 in meinem Schnellversuch)
Field all_your_base_are_belong_to_us$ ;Also hier alle Daten rein die du sonst noch brauchst
End Type

Global binary_root.node

;Suche nach einem Schlüssel
Function Search.node(key#)
Local p.node=binary_root
While p<>Null
If key=p\key Then Exit
If key<p\key Then
p=p\Left
Else
p=p\Right
EndIf
Wend
Return p
End Function

;Minimalster Wert im gesamten Baum
Function Minimum.node()
Local q.node=binary_root
While q\Left<>Null
q=q\Left
Wend
Return q
End Function

;Maximalster Wert im gesamten Baum
Function Maximum.node()
Local q.node=binary_root
While q\Right<>Null
q=q\Right
Wend
Return q
End Function

;Minimalster Wert im durch q gegebenen Unterbaum
Function MinimumFrom.node(q.node)
If q=Null Then Return Null
While q\Left<>Null
q=q\Left
Wend
Return q
End Function

;Maximalster Wert im durch q gegebenen Unterbaum
Function MaximumFrom.node(q.node)
If q=Null Then Return Null
While q\Right<>Null
q=q\Right
Wend
Return q
End Function

;Nächster Nachfolger von q (nach Schlüssel geordnet)
Function Successor.node(q.node)
If q\Right<>Null Then
Return MinimumFrom(q\Right)
Else
Local p.node=q\parent
While p<>Null
If q<>p\Right Then Exit
q=p
p=p\parent
Wend
Return p
EndIf
End Function

;Nächster Vorgänger von q
Function Predecessor.node(q.node)
If q\Left<>Null Then
Return MaximumFrom(q\Left)
Else
Local p.node=q\parent
While p<>Null
If q<>p\Left Then Exit
q=p
p=p\parent
Wend
Return p
EndIf
End Function

;Neues Element einfügen
Function InsertNode(q.node)
Local r.node=Null
Local p.node=binary_root
While p<>Null
r=p
If q\key<p\key Then
p=p\Left
Else
p=p\Right
EndIf
Wend
q\parent=r
q\Left=Null
q\Right=Null
If r=Null Then
binary_root=q
Else
If q\key<r\key Then
r\Left=q
Else
r\Right=q
EndIf
EndIf
End Function

;Element entfernen
Function DeleteNode(q.node)
If q=Null Then Return
;Fall 1 - keine Nachfolger
If q\Right=Null And q\Left=Null Then
Delete q
Return
EndIf
Local r.node
If q\Right=Null Or q\Left=Null Then
;Fall 2 - genau 1 Nachfolger
r=q
Local p.node=r\parent
If r\Left<>Null Then
r=r\Left
Else
r=r\Right
EndIf
If p=Null Then
binary_root=r
Else
If q=p\Right Then
p\Right=r
Else
p\Left=r
EndIf
EndIf
Else
;Fall 3 - 2 Nachfolger
r=Successor(q)
r\parent\Left=r\Right
r\Left=q\Left
r\Right=q\Right
r\parent=q\parent
EndIf
Delete q
End Function


und hier der Beispielcode der eigentlich nur dafür konstruiert ist die Schnelligkeit zu demonstrieren - er ist ziemlich sinnlos (wer würde für einen identifizierenden Schlüssel einen Zufallswert nehmen Rolling Eyes )

BlitzBasic: [AUSKLAPPEN]
;Frei erfundenes Anwendungsbeispiel des binären Suchbaumes:
;Man nehme an es gibt Personen (Hier mal nur Name) die durch eine Kennzahl identifiziert werden

Include "binarytree.bb"

SeedRnd MilliSecs()

Global entries=10000 ;Anzahl der Einträge mit denen getestet wird

Dim ids(entries-1) ;Zwischenspeicher der generierten Personennummern - damit man nachher nach ihnen suchen kann
;Anmerkung: Der ganze Umstand dass die Nummern generiert und nicht einfach fortlaufend gezählt werden ist der,
;dass bei einer fortlaufenden Zählen der Sinn der binären Bäume verloren geht - da könnte man ja gleich n Array nehmen...


Local n.node
Local time=MilliSecs()
For i=0 To entries-1 ;1000 Einträge
n=New node
n\key=Rand(1,1000000) ;Irgendeine Zahl generiern, event. doppelt vorkommende Zahlen werden einfach mal ignoriert
ids(i)=n\key
n\all_your_base_are_belong_to_us$="x"
InsertNode(n)
Next
Print "Erstellen von "+entries+" Elementen: "+(MilliSecs()-time)+"ms"

;Eigentliche Demo: Zufällige Einträge suchen
Local searches=10000
time=MilliSecs()
For i=1 To searches
num=ids(Rand(0,entries-1))
n=Search(num)
;DebugLog "Person Nr. "+num+" ist "+n\all_your_base_are_belong_to_us$
Next
Print searches+" Suchen in "+entries+" Elementen dauerten "+(MilliSecs()-time)+"ms"
;Debugmodus: 26ms, ohne Debug 6

time=MilliSecs()
For i=0 To entries-1
n=Search(ids(i))
DeleteNode(n)
Next
Print "In "+(MilliSecs()-time)+"ms wurden alle wieder gesucht & gelöscht"

WaitKey()
End


Man kann sich übrigens n bisschen spielen und wirklich Namen einsetzen anstatt dem "x". Ich habe für meine Tests zum Beispiel den Namen-Generator von SilverKnee benutzt.

Ja... das wars erstmal.
Eventuell krieg ich wiedermal Lust darauf und setz mich dran den Baum zu balancieren... mal schauen. So ist es halt mal n Codeschnipsel der hier hoffentlich gut aufgehoben ist.

mfG, Christoph.
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9
  • Zuletzt bearbeitet von Eingeproggt am Sa, Mai 01, 2010 20:13, insgesamt 3-mal bearbeitet

mpmxyz

BeitragMo, Apr 12, 2010 18:11
Antworten mit Zitat
Benutzer-Profile anzeigen
(Ich traue dem Code mal ungetestet. Wink)
Schöne Sache!
Stringvergleiche sollten aber möglich sein, indem du aus "key#" "key$" machst.
Womit möchtest du denn die Suchbäume balancieren?
Machst du sie zu Rot-Schwarz-Bäumen?
Diese nutzt nämlich BlitzMax.
mfG
mpmxyz
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer

Eingeproggt

BeitragMo, Apr 12, 2010 18:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habs seit gestern nicht weiter gemacht.
Aber ich traue meinen Augen nicht Shocked

Ich dachte immer, um Strings zu sortieren müsste man manuell alle Zeichen durchgehen und die mittels Asc in eine Zahl wandeln.
Und auf deine Aussage hin probierte ich das grad...

Code: [AUSKLAPPEN]
DebugLog "abc">"bca" ;0
DebugLog "abc"<"bca" ;1


ja is das geil - Danke, da hab ich grad was gelernt Smile
Werd sofort editieren oben.

Was die Balance angeht so dachte ich an AVL-Bäume (auch für die hab ich da Pseudo Code herum liegen ^^)
Muss gestehen dass ich "Rot-Schwarz-Bäume" bis gestern nicht kannte - wo mich bereits ein Mitlgied dieses Forums in ICQ darauf angesprochen hatte.

mfG, Christoph.

EDIT: So, geändert (und auch gleich die Float-Sache entfernt, weil wenn schon Zahlen dann werden die Schlüssel ja doch meist Int sein)
Allerdings bitte ich zu berücksichtigen dass String-Vergleiche logischerweise langsamer sind als Zahlen zu vergleichen - das ist nunmal so, ich hätte es auch nicht schneller machen können.
Für numerische Schlüssel ist daher % ganz klar zu bevorzugen (ich hab mal getestet: 26ms <> 756ms!)
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group