ich bin über Computercraft (falls das ein Begriff ist) und Lua zum Programmieren gekommen und habe sehr bald Blut geleckt
Aus diesem Grund wollte ich mich mal etwas anspruchvollerem zuwenden und habe einen simplen Binärbaum zusammengetippt. Soweit scheint auch alles zur funktionieren, jedoch wollte ich das ganze dann zu einem AVL ausweiten, was mir leider nicht so ganz gelingen will:
Die Ausgabe meines kleinen Testskripts stimmt in so fern, als die Höhen- und Balancewerte der einzelnen Knoten korrekt sind, jedoch scheine ich bei der Rotation irgendwo Mist gebaut zu haben, da es, wenn ich die Zeilen 107 und 119 wieder einfüge, zwar einen Baum kriege und er die Rotation auch triggert (Ausgabe: "links"), jedoch in einer Endlosschliefe hängen zu bleiben scheint (zumindest schließe ich dies aus 100% auf einem Kern und fehlender Terminierung des Skripts).
Ich hoffe, jemand kann mir sagen, was genau ich übersehen habe...
Vorweg schon mal Danke für eure Zeit
LG
Hier das BTree Skript (ich hoffe, die Kommentare sind nicht allzu störend, ich musste mir das selbst notieren, was ich da eigentlicht tue ):
Code: Alles auswählen
#!/usr/bin/python3
__all__ = ["BBaum", "BKnoten"]
#------------------------------------------------------------------------------
# B-Tree Klasse
#------------------------------------------------------------------------------
class BBaum:
"""
Stellt eine B-Tree Instanz bereit. Fuer Informationen zu den Funktionen folgendes
eingeben:
baum.[Funktion].__doc__
Methoden:
__init__ - Erstellt eine Instanz des B-Tree
__del__ - Loescht die Instanz
auflisten - Listet alle Elemente im Baum auf
einfuegen - Fuegt einen Knoten hinzu
get_groessten - Gibt den groessten Unterknoten zurueck
get_kleinsten - Gibt den kleinste Unterknoten zurueck
get_root - Gibt den Wurzelknoten zurueck
ist_leer - Gibt an, ob der Baum Knoten enthaelt
loeschen - Loescht einen Knoten
suchen - Durchsucht den Baum
"""
__all__ = ["__del__", "__init__", "einfuegen", "get_groessten",
"get_kleinsten", "get_root", "ist_leer", "loeschen", "suchen"]
__name__ = "BBaum"
#--------------------------------------------------------------------------
# init
#--------------------------------------------------------------------------
def __init__(self, wurzel, pointer = None):
"""
Verwendung:
baum = BBaum(wurzel)
wurzel ist der Wurzelschluessel des Baumes
"""
self.__root = BKnoten(wurzel, pointer = pointer)
#--------------------------------------------------------------------------
# del
#--------------------------------------------------------------------------
def __del__(self):
"""
Verwendung:
baum.__del__()
"""
while self.__root.Rechts or self.__root.Links:
if self.__root.Links:
self.loeschen(self.__root.Links)
else:
self.loeschen(self.__root.Rechts)
del self.__root
#--------------------------------------------------------------------------
# auflisten
#--------------------------------------------------------------------------
def auflisten(self):
"""
Gibt alle Knotenschluessel und die zugehoerigen Pointer im Baum ausgehen
Verwendung:
a = baum.auflisten()
"""
liste = []
self.__auflisten_recur(self.__root, liste)
return liste
#--------------------------------------------------------------------------
# __auflisten_recur
#--------------------------------------------------------------------------
def __auflisten_recur(self, ober, liste):
if ober.Links:
self.__auflisten_recur(ober.Links, liste)
liste.append({ober.Key:{"H":ober.Hoehe, "Bal":ober.Balance}})
if ober.Rechts:
self.__auflisten_recur(ober.Rechts, liste)
#--------------------------------------------------------------------------
# einfuegen
#--------------------------------------------------------------------------
def einfuegen(self, key, pointer):
"""
Verwendung:
baum.einfuegen(key, pointer)
key ist der Schluessel, unter dem der Eintrag abgelegt werden soll, pointer
enthaelt den Verweis auf die Tabelle.
"""
if self.__root.Key:
self.__einfuegen_recur(self.__root, key, pointer)
else:
self.__root.Key = key
self.__root.Pointer = pointer
#--------------------------------------------------------------------------
# __einfuegen_recur
#--------------------------------------------------------------------------
def __einfuegen_recur(self, ober, key, pointer):
if key > ober.Key:
if not ober.Rechts:
ober.Rechts = BKnoten(key, ober, pointer)
else:
self.__einfuegen_recur(ober.Rechts, key, pointer)
ober.hoehe_errechnen()
#ober.balance_errechnen()
if ober.Balance == -2:
if ober.Rechts.Balance == -1:
print("rechts")
# hier muss unterschieden werden, damit bereits vorhandene Schluessel
# nicht erneut eingefuegt werden.
elif key < ober.Key:
if not ober.Links:
ober.Links = BKnoten(key, ober, pointer)
else:
self.__einfuegen_recur(ober.Links, key, pointer)
ober.hoehe_errechnen()
#ober.balance_errechnen()
if ober.Balance == 2:
if ober.Links.Balance == 1:
print("links")
tmp = ober.Links
ober.Links = tmp.Rechts
tmp.Rechts = ober
ober = tmp
ober.hoehe_errechnen()
ober.balance_errechnen()
#--------------------------------------------------------------------------
# get_groessten
#--------------------------------------------------------------------------
def get_groessten(self, ober):
"""
Verwendung:
baum.get_groessten(ober)
Gibt den groessten Unterknoten ausgehend von ober zurueck
"""
while ober.Rechts:
ober = ober.Rechts
return ober
#--------------------------------------------------------------------------
# get_kleinsten
#--------------------------------------------------------------------------
def get_kleinsten(self, ober):
"""
Verwendung:
baum.get_kleinsten(ober)
Gibt den kleinsten Unterknoten ausgehend von ober zurueck
"""
while ober.Links:
ober = ober.Links
return ober
#--------------------------------------------------------------------------
# get_leer
#--------------------------------------------------------------------------
def get_leer(self):
"""
Prueft, ob der Baum leer ist und gibt das Ergebnis in die Variable
Leer aus.
Verwendung:
baum.Leer
False
"""
if self.__root.Key:
return False
else:
return True
Leer = property(get_leer)
#--------------------------------------------------------------------------
# get_root
#--------------------------------------------------------------------------
def get_root(self):
"""
Gibt den Wurzelknoten in der Variable Root aus.
Verwendung:
baum.Root
<BTree.BKnoten object at xyz>
"""
return self.__root
Root = property(get_root)
#--------------------------------------------------------------------------
# loeschen
#--------------------------------------------------------------------------
def loeschen(self, knoten):
"""
Verwendung:
baum.loeschen(knoten)
knoten muss ein Knoten-Objekt des Baumes sein.
"""
if knoten.Rechts == None and knoten.Links == None:
self.__loesche_blatt(knoten)
elif knoten.Rechts == None or knoten.Links == None:
self.__loesche_einzeln(knoten)
else:
# ersetzt den Knoten durch den niedrigsten Unterknoten ausgehend
# vom rechten Knoten, da der kleinste rechte Wert grosser, als der
# groesste linke Wert ist
minRechts = self.get_kleinsten(knoten.Rechts)
knoten.Key = minRechts.Key
knoten.Pointer = minRechts.Pointer
self.loeschen(minRechts)
#--------------------------------------------------------------------------
# __loesche_blatt
#--------------------------------------------------------------------------
def __loesche_blatt(self, knoten):
if knoten is self.__root:
self.__root.Key = None
self.__root.Pointer = None
else:
if knoten.Eltern.Rechts is knoten:
knoten.Eltern.Rechts = None
else:
knoten.Eltern.Links = None
del knoten
#--------------------------------------------------------------------------
# __loesche_einzeln
#--------------------------------------------------------------------------
def __loesche_einzeln(self, knoten):
kind = None
if knoten.Links:
kind = knoten.Links
else:
kind = knoten.Rechts
# loescht die Wurzel und ersetzt sie durch einen Unterknoten
if knoten is self.__root:
self.__root = kind
kind.Eltern = None
del knoten
else:
# schneidet den Knoten aus und verlinkt den ehemaligen
# Unterknoten mit dem ehemaligen Elternknoten
eltern = knoten.Eltern
if knoten is eltern.Links:
eltern.Links = kind
else:
eltern.Rechts = kind
kind.Eltern = eltern
del knoten
#--------------------------------------------------------------------------
# suchen
#--------------------------------------------------------------------------
def suchen(self, key):
"""
Verwendung:
baum.suchen(key)
key ist der Schluessel, nach dem gesucht werden soll. Bei Erfolg wird der
Knoten zurueck gegeben, andernfalls None.
"""
ober = self.__root
while True:
if key > ober.Key:
if ober.Rechts:
ober = ober.Rechts
else:
return None
elif key < ober.Key:
if ober.Links:
ober = ober.Links
else:
return None
else:
return ober
#------------------------------------------------------------------------------
# B-Knoten Klasse
#------------------------------------------------------------------------------
class BKnoten:
"""
Klasse der B-Tree Knoten.
Methoden:
__init__ - Erstellt einen neuen Knoten
__del__ - Loescht einen Knoten
get_bal - Gibt die Balance am Knoten zurueck
set_bal - Setzt die Balance am Knoten
get_eltern - Gibt den Elternknoten zurueck
set_eltern - Setzt den Elternknoten
get_key - Gibt den Schluessel des Knotens aus
set_key - Setzt den Schluessel des Knotens
get_links - Gibt den kleineren Wert zurueck
set_links - Setzt den kleineren Wert
get_pointer - Gibt den Pointer zurueck
set_pointer - Setzt den Pointer
get_rechts - Gibt den groesseren Wert zurueck
set_rechts - Setzt den groesseren Wert
"""
__all__ = ["__del__", "__init__", "get_eltern", "get_key", "get_links",
"get_pointer", "get_rechts", "set_eltern", "set_key",
"set_links", "set_pointer", "set_rechts"]
__name__ = "BKnoten"
#--------------------------------------------------------------------------
# init
#--------------------------------------------------------------------------
def __init__(self, key, eltern = None, pointer = None):
self.__balance = 0
self.__eltern = eltern
self.__hoehe = 1
self.__key = key
self.__links = None
self.__pointer = pointer
self.__rechts = None
#--------------------------------------------------------------------------
# del
#--------------------------------------------------------------------------
def __del__(self):
del self.__balance
del self.__eltern
del self.__hoehe
del self.__key
del self.__links
del self.__pointer
del self.__rechts
#--------------------------------------------------------------------------
# balance_errechnen
#--------------------------------------------------------------------------
def balance_errechnen(self):
"""
Gibt die aktuelle Balance des Baumes am Knoten zurueck
Verwendung:
knoten.balance_errechnen()
"""
if self.Links:
if self.Rechts:
self.Balance = self.Links.Hoehe - self.Rechts.Hoehe
else:
self.Balance = self.Links.Hoehe
else:
if self.Rechts:
self.Balance = -self.Rechts.Hoehe
else:
self.Balance = 0
#--------------------------------------------------------------------------
# hoehe_errechnen
#--------------------------------------------------------------------------
def hoehe_errechnen(self):
"""
Errechnet die aktuelle Hoehe des Kontens im Baum und speichert diese
in der Variable Hoehe
Verwendung:
knoten.hoehe_errechnen()
"""
if not self.Links:
if not self.Rechts:
self.Hoehe = 1
else:
self.Hoehe = 1 + self.Rechts.Hoehe
else:
if not self.Rechts:
self.Hoehe = 1 + self.Links.Hoehe
else:
self.Hoehe = max(self.Links.Hoehe, self.Rechts.Hoehe) + 1
#--------------------------------------------------------------------------
# get_balance
#--------------------------------------------------------------------------
def get_bal(self):
return self.__balance
#--------------------------------------------------------------------------
# get_eltern
#--------------------------------------------------------------------------
def get_eltern(self):
return self.__eltern
#--------------------------------------------------------------------------
# get_hoehe
#--------------------------------------------------------------------------
def get_hoehe(self):
return self.__hoehe
#--------------------------------------------------------------------------
# get_key
#--------------------------------------------------------------------------
def get_key(self):
return self.__key
#--------------------------------------------------------------------------
# get_links
#--------------------------------------------------------------------------
def get_links(self):
return self.__links
#--------------------------------------------------------------------------
# get_pointer
#--------------------------------------------------------------------------
def get_pointer(self):
return self.__pointer
#--------------------------------------------------------------------------
# get_rechts
#--------------------------------------------------------------------------
def get_rechts(self):
return self.__rechts
#--------------------------------------------------------------------------
# set_balance
#--------------------------------------------------------------------------
def set_bal(self, bal):
self.__balance = bal
#--------------------------------------------------------------------------
# set_eltern
#--------------------------------------------------------------------------
def set_eltern(self, eltern):
self.__eltern = eltern
#--------------------------------------------------------------------------
# set_hoehe
#--------------------------------------------------------------------------
def set_hoehe(self, hoehe):
self.__hoehe = hoehe
#--------------------------------------------------------------------------
# set_key
#--------------------------------------------------------------------------
def set_key(self, key):
self.__key = key
#--------------------------------------------------------------------------
# set_links
#--------------------------------------------------------------------------
def set_links(self, links):
self.__links = links
#--------------------------------------------------------------------------
# set_pointer
#--------------------------------------------------------------------------
def set_pointer(self, pointer):
self.__pointer = pointer
#--------------------------------------------------------------------------
# set_rechts
#--------------------------------------------------------------------------
def set_rechts(self, rechts):
self.__rechts = rechts
#--------------------------------------------------------------------------
# Propertys
#--------------------------------------------------------------------------
Balance = property(get_bal, set_bal)
Eltern = property(get_eltern, set_eltern)
Hoehe = property(get_hoehe, set_hoehe)
Key = property(get_key, set_key)
Links = property(get_links, set_links)
Pointer = property(get_pointer, set_pointer)
Rechts = property(get_rechts, set_rechts)
Code: Alles auswählen
#!/usr/bin/python3
import BTree
tree = BTree.BBaum(10, "Root")
liste = [5, 12, 2, 8, 11, 13, 1, 4, 7, 9, 3]
for a in liste:
tree.einfuegen(a, "k")
for e in tree.auflisten():
print(e)