class_name BST class _Node extends RefCounted: var value: int var left: Option = Option.none var right: Option = Option.none func _init(value: int) -> void: self.value = value func size() -> int: return BST.size(self) func has_children() -> bool: return BST.has_children(self) func balance() -> _Node: return BST.balance(self).unwrap() func insert(value: int) -> _Node: return BST.insert(self, value) func search(value: int) -> Option: return BST.search(self, value) func remove(value: int) -> Option: return BST.remove(self, value) func iter() -> Iterator: return BST.iter(self) static func from(value: int) -> _Node: return _Node.new(value) static func size(node: _Node) -> int: var left = node.left.map(size).or_default(0) var right = node.right.map(size).or_default(0) return left + right + 1 static func _store_in_order(_root: Option, nodes: Array[_Node] = []) -> Array[_Node]: if _root.is_none(): return nodes var root = _root.unwrap() _store_in_order(root.left, nodes) nodes.append(root) _store_in_order(root.right, nodes) return nodes static func _build_balanced_tree(nodes: Array[_Node], start: int = 0, end: int = len(nodes) - 1) -> Option: if start > end: return Option.none var mid: int = (start + end) / 2 var root = nodes[mid] root.left = _build_balanced_tree(nodes, start, mid - 1) root.right = _build_balanced_tree(nodes, mid + 1, end) return Option.some(root) static func balance(root: _Node) -> Option: return _build_balanced_tree(_store_in_order(Option.some(root))) static func has_children(node: _Node) -> bool: return node.left.is_none() and node.right.is_none() static func _insert(_root: Option, node: _Node) -> _Node: if _root.is_none(): return node var root = _root.unwrap() if root.value == node.value: return root elif root.value < node.value: root.right = Option.some(_insert(root.right, node)) else: root.left = Option.some(_insert(root.left, node)) return root static func insert(root: _Node, value: int) -> _Node: return _insert(Option.some(root), _Node.new(value)) static func _search(_root: Option, value: int) -> Option: if _root.is_none(): return Option.none var root = _root.unwrap() if root.value == value: return _root if root.value < value: return _search(root.right, value) return _search(root.left, value) static func search(root: _Node, value: int) -> Option: return _search(Option.some(root), value) static func _get_successor(node: _Node) -> _Node: var current = node.right while current.is_some() and current.left.is_some(): current = node.left.unwrap() return current static func _remove(_root: Option, value: int) -> Option: if _root.is_none(): return _root var root = _root.unwrap() if root.value < value: return _remove(root.right, value) elif root.value > value: return _remove(root.left, value) else: if root.right.is_none(): return root.left elif root.left.is_none(): return root.right var successor = _get_successor(root) root.value = successor.value root.right = remove(root.right, successor.value) return Option.some(root) static func remove(root: _Node, value: int) -> Option: return _remove(Option.some(root), value) static func traverse(root: _Node, fn: Callable): root.left.map(fn.call) fn.call(root.value) root.right.map(fn.call) static func iter(node: _Node) -> Iterator: var iters = Option.collect_some([ node.left.map(iter), Option.some(SingletonIterator.new(node.value)), node.right.map(iter) ], true).unwrap() var iter_arr: Array[Iterator] iter_arr.assign(iters) return FusedIterator.new(iter_arr)