import enum class NodeType(enum.IntEnum): LEAF = 0 UNARY = 1 BINARY = 2 class Node: def __init__(self, value, left=None, right=None, parent=None): self.parent = parent self.left = left self.right = right self.value = value self.rank = 0 @property def type(self): if self.left and self.right: return NodeType.BINARY if self.left or self.right: return NodeType.UNARY return NodeType.LEAF def __repr__(self): return f"Node(value={self.value}, rank={self.rank}, left={self.left}, right={self.right}, parent={self.parent})" def __str__(self): return f"Node(value={self.value}, rank={self.rank})" @staticmethod def height(node): return 1 + max(Node.height(node.left), Node.height(node.right)) if node else -1 @staticmethod def rank(node): return -1 if not node else node.rank @staticmethod def difference(node, parent=None): if not parent: parent = node.parent if node else None return Node.rank(parent) - Node.rank(node) @staticmethod def differences(node): node_rank = Node.rank(node) (left, right) = (node.left, node.right) if node else (None, None) return (node_rank - Node.rank(left), node_rank - Node.rank(right)) def promote(self): self.rank += 1 return self def demote(self): self.rank -= 1 return self @staticmethod def rotate_right(x): parent = x.parent y = x.left z = x.right assert y is not None if parent: if parent.left is x: parent.left = y else: parent.right = y x.left = y.right if x.left: x.left.parent = x y.right = x x.parent = y y.parent = parent return y @staticmethod def rotate_left(x): parent = x.parent y = x.left z = x.right assert z is not None if parent: if parent.left is x: parent.left = z else: parent.right = z x.right = z.left if x.right: x.right.parent = x z.left = x x.parent = z z.parent = parent return z @staticmethod def find_parent_node(value, node, missing=True): new_node = node while new_node and (missing or new_node.value != value): node = new_node new_node = node.left if value < node.value else node.right return node @staticmethod def search(value, node): while node and node.value != value: node = node.left if value < node.value else node.right return node @staticmethod def minimum(node): while node.left: node = node.left return node @staticmethod def maximum(node): while node.right: node = node.right return node