|
@ -3,6 +3,7 @@ from django.db import transaction |
|
|
# NOTE: node.prev a node.succ jsou implementovány přímo v models.TreeNode |
|
|
# 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: 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: 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. |
|
|
# Slouží k debugování pro rychlé získání představy o podobě podstromu pod tímto TreeNode. |
|
|
def print_tree(node,indent=0): |
|
|
def print_tree(node,indent=0): |
|
@ -347,55 +348,76 @@ def swap_pred(node): |
|
|
|
|
|
|
|
|
# Rotace stromu |
|
|
# Rotace stromu |
|
|
# Dokumentace viz wiki: |
|
|
# Dokumentace viz wiki: |
|
|
# (lower bude jednoduchá rotace, ne mega, existence jednoduché rotace mi došla až po nakreslení obrázku) |
|
|
|
|
|
def raise_node(node): |
|
|
def raise_node(node): |
|
|
if node is None: |
|
|
if node is None: |
|
|
raise TreeLibError("Nelze přesunout None. Tohle by se nemělo stát.") |
|
|
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) |
|
|
# 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 |
|
|
D = node |
|
|
C = get_parent(D) |
|
|
C = get_parent(D) |
|
|
E = C.succ |
|
|
if C is None: |
|
|
subtree4_head = D.first_child |
|
|
raise TreeLibError("Nelze povýšit vrchol, jenž nemá otce.") |
|
|
subtree4_tail = last_brother(subtree4_head) |
|
|
E = C.succ # Může být None a ničemu to nevadí |
|
|
subtree3P_head = D.succ |
|
|
subtree4_head = D.first_child # Může být None, ale pak se musí z 3P udělat přímo potomek D |
|
|
subtree3L_head = C.first_child |
|
|
subtree4_tail = last_brother(subtree4_head) # Měl by být None právě když je sub4_head=None |
|
|
subtree3L_tail = safe_pred(D) |
|
|
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... |
|
|
# Prostor pro motlitbu... |
|
|
pass |
|
|
pass |
|
|
|
|
|
|
|
|
# Amen. |
|
|
# 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() |
|
|
C.save() |
|
|
D.succ = E |
|
|
D.succ = E # Nespadne |
|
|
D.save() |
|
|
D.save() |
|
|
|
|
|
|
|
|
|
|
|
if subtree3L_tail is not None: |
|
|
subtree3L_tail.succ = None |
|
|
subtree3L_tail.succ = None |
|
|
subtree3L_tail.save() |
|
|
subtree3L_tail.save() |
|
|
subtree4_tail.succ = subtree3P.head |
|
|
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() |
|
|
subtree4_tail.save() |
|
|
|
|
|
else: |
|
|
|
|
|
D.first_child = subtree3P_head |
|
|
|
|
|
D.save() |
|
|
|
|
|
|
|
|
# To by mělo být všechno... |
|
|
# 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): |
|
|
def lower_node(node): |
|
|
if node is None: |
|
|
if node is None: |
|
|
raise TreeLibError("Nelze přesunout None. Tohle by se nemělo stát.") |
|
|
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) |
|
|
# Pojmenování viz WIKI (as of 2020-03-19 01:33:44 GMT+1) |
|
|
# FIXME: Velmi naivní, chybí error checky |
|
|
# FIXME: Velmi naivní, chybí error checky |
|
|
C = node |
|
|
C = node |
|
|
D = C.succ |
|
|
D = C.succ # Může být None a ničemu to nevadí |
|
|
B = safe_pred(C) |
|
|
B = safe_pred(C) |
|
|
subtree2_head = B.first_child |
|
|
if B is None: |
|
|
subtree2_tail = last_brother(subtree2_head) |
|
|
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... |
|
|
# Prostor pro motlitbu... |
|
|
pass |
|
|
pass |
|
|
|
|
|
|
|
|
# Amen. |
|
|
# 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() |
|
|
B.save() |
|
|
|
|
|
if subtree2_tail is not None: |
|
|
subtree2_tail.succ = C |
|
|
subtree2_tail.succ = C |
|
|
subtree2_tail.save() |
|
|
subtree2_tail.save() |
|
|
|
|
|
else: |
|
|
|
|
|
assert subtree2_head is None |
|
|
|
|
|
B.first_child = C |
|
|
|
|
|
B.save() |
|
|
|
|
|
|
|
|
# To by mělo být všechno... |
|
|
# To by mělo být všechno... |
|
|
|
|
|
|
|
|