python/node.py

140 lines
3 KiB
Python
Raw Normal View History

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