class BSTNode:
    def __init__(self, name: str, phone: str):
        self.name = name
        self.phone = phone
        self.left = None
        self.right = None

class BinarySearchTree:
    def __init__(self):
        self.root = None
    
    def insert(self, name: str, phone: str) -> None:
        if self.root is None:
            self.root = BSTNode(name, phone)
            return
        
        current = self.root
        while True:
            if name < current.name:
                if current.left is None:
                    current.left = BSTNode(name, phone)
                    break
                current = current.left
            elif name > current.name:
                if current.right is None:
                    current.right = BSTNode(name, phone)
                    break
                current = current.right
            else:
                current.phone = phone
                break
    
    def search(self, name: str):
        current = self.root
        while current:
            if name == current.name:
                return current.phone
            elif name < current.name:
                current = current.left
            else:
                current = current.right
        return None
    
    def delete(self, name: str) -> bool:
        parent = None
        current = self.root
        
        while current and current.name != name:
            parent = current
            if name < current.name:
                current = current.left
            else:
                current = current.right
        
        if current is None:
            return False
        
        if current.left is None and current.right is None:
            if parent is None:
                self.root = None
            elif parent.left == current:
                parent.left = None
            else:
                parent.right = None
        
        elif current.left is None:
            if parent is None:
                self.root = current.right
            elif parent.left == current:
                parent.left = current.right
            else:
                parent.right = current.right
        
        elif current.right is None:
            if parent is None:
                self.root = current.left
            elif parent.left == current:
                parent.left = current.left
            else:
                parent.right = current.left
        
        else:
            successor_parent = current
            successor = current.right
            while successor.left:
                successor_parent = successor
                successor = successor.left
            
            current.name = successor.name
            current.phone = successor.phone
            
            if successor_parent.left == successor:
                successor_parent.left = successor.right
            else:
                successor_parent.right = successor.right
        
        return True
    
    def inorder(self) -> list:
        result = []
        stack = []
        current = self.root
        
        while stack or current:
            while current:
                stack.append(current)
                current = current.left
            current = stack.pop()
            result.append({'name': current.name, 'phone': current.phone})
            current = current.right
        
        return result
    
    def get_height(self) -> int:
        if self.root is None:
            return 0
        
        queue = [(self.root, 1)]
        max_height = 0
        
        while queue:
            node, height = queue.pop(0)
            max_height = max(max_height, height)
            if node.left:
                queue.append((node.left, height + 1))
            if node.right:
                queue.append((node.right, height + 1))
        
        return max_height
    
    def get_size(self) -> int:
        count = 0
        stack = [self.root] if self.root else []
        
        while stack:
            node = stack.pop()
            count += 1
            if node.left:
                stack.append(node.left)
            if node.right:
                stack.append(node.right)
        
        return count
    
    def clear(self) -> None:
        self.root = None
    
    def is_empty(self) -> bool:
        return self.root is None