diff --git a/seminar/treelib.py b/seminar/treelib.py index a17d9aee..bd47da4d 100644 --- a/seminar/treelib.py +++ b/seminar/treelib.py @@ -3,6 +3,7 @@ from django.db import transaction # NOTE: node.prev a node.succ jsou implementovány přímo v models.TreeNode # TODO: Všechny tyto funkce se naivně spoléhají na to, že jako parametr dostanou nějaký TreeNode (některé možná zvládnou i None) # TODO: Chceme, aby všechno nějak zvládlo None jako parametr. +# TODO: Do nějakých consistency-checků přidat hledání polo-sirotků (kteří nesplňují invarianty) # Slouží k debugování pro rychlé získání představy o podobě podstromu pod tímto TreeNode. def print_tree(node,indent=0): @@ -347,55 +348,76 @@ def swap_pred(node): # Rotace stromu # Dokumentace viz wiki: -# (lower bude jednoduchá rotace, ne mega, existence jednoduché rotace mi došla až po nakreslení obrázku) def raise_node(node): if node is None: raise TreeLibError("Nelze přesunout None. Tohle by se nemělo stát.") # Pojmenování viz WIKI (as of 2020-03-19 01:33:44 GMT+1) - # FIXME: Velmi naivní, chybí error checky + # FIXME: Trochu méně naivní, nevěřím tomu, prosím otestovat D = node C = get_parent(D) - E = C.succ - subtree4_head = D.first_child - subtree4_tail = last_brother(subtree4_head) - subtree3P_head = D.succ - subtree3L_head = C.first_child - subtree3L_tail = safe_pred(D) + if C is None: + raise TreeLibError("Nelze povýšit vrchol, jenž nemá otce.") + E = C.succ # Může být None a ničemu to nevadí + subtree4_head = D.first_child # Může být None, ale pak se musí z 3P udělat přímo potomek D + subtree4_tail = last_brother(subtree4_head) # Měl by být None právě když je sub4_head=None + subtree3P_head = D.succ # Může být None a ničemu to nevadí + subtree3L_tail = safe_pred(D) # Pokud je None, D je první syn C a C má tedy skončit bezdětný # Prostor pro motlitbu... pass # Amen. - C.succ = D + # Teď už nesmíme spadnout, protože jinak skončíme se stromem v nekonzistentním stavu + C.succ = D # Nespadne C.save() - D.succ = E + D.succ = E # Nespadne D.save() - subtree3L_tail.succ = None - subtree3L_tail.save() - subtree4_tail.succ = subtree3P.head - subtree4_tail.save() + + if subtree3L_tail is not None: + subtree3L_tail.succ = None + subtree3L_tail.save() + else: + assert C.first_child is D + C.first_child = None + C.save() + + if subtree4_tail is not None: + subtree4_tail.succ = subtree3P_head + subtree4_tail.save() + else: + D.first_child = subtree3P_head + D.save() # To by mělo být všechno... +# (lower bude jednoduchá rotace, ne mega, existence jednoduché rotace mi došla až po nakreslení obrázku) def lower_node(node): if node is None: raise TreeLibError("Nelze přesunout None. Tohle by se nemělo stát.") # Pojmenování viz WIKI (as of 2020-03-19 01:33:44 GMT+1) # FIXME: Velmi naivní, chybí error checky C = node - D = C.succ + D = C.succ # Může být None a ničemu to nevadí B = safe_pred(C) - subtree2_head = B.first_child - subtree2_tail = last_brother(subtree2_head) + if B is None: + raise TreeLibError("Nelze ponížit prvního syna (není pod co)") + subtree2_head = B.first_child # Je-li None, pak se z C má stát první syn + subtree2_tail = last_brother(subtree2_head) # None iff head=None, doufám # Prostor pro motlitbu... pass # Amen. - B.succ = D + # Teď už nesmíme spadnout, protože jinak skončíme se stromem v nekonzistentním stavu + B.succ = D # Nespadne B.save() - subtree2_tail.succ = C - subtree2_tail.save() + if subtree2_tail is not None: + subtree2_tail.succ = C + subtree2_tail.save() + else: + assert subtree2_head is None + B.first_child = C + B.save() # To by mělo být všechno...