def ll_insert(head, name, phone):
   
   new_node = {'name': name, 'phone': phone, 'next': None}

   if head is None:
       return new_node
   
   current = head
   while current['next'] is not None:
    current = current['next']

    current['next'] = new_node
    return head

def ll_find(head, name):
    current = head
    while current is not None:
        if current['name'] == name:
            return current['phone']
        current = current['next']
    return None

def ll_delete(head, name):
    if head is None:
        return None
    if head['name'] == name:
        return head['next']
    current = head
    while current['next'] is not None:
        if current['next']['name'] == name:
            current['next'] = current['next']['next']
            return head
        current = current['next']
    return head

def ll_list_all(head):
    records = []
    current = head

    while current is  not None:
        records.append((current['name'], current['phone']))
        current = current['next']
    records.sort(key=lambda x: x[0])
    return records

def hash_function(name, table_size):
    total = 0
    for ch in name:
        total = (total*31 + ord(ch)) % table_size
    return total

def ht_create(size=1000):
    return [None]*size

def ht_insert(buckets, name, phone):
    idx = hash_function(name, len(buckets))
    buckets[idx] = ll_insert(buckets[idx], name, phone)
    return buckets

def ht_find(buckets, name):
    idx = hash_function(name, len(buckets))
    return ll_find(buckets[idx], name)

def ht_delete(buckets, name):
    idx = hash_function(name, len(buckets))
    buckets[idx] = ll_delete(buckets[idx], name)
    return buckets

def ht_list_all(buckets):
    records = []
    for bucket in buckets:
        current = bucket
        while current is not None:
            records.append((current['name'], current['phone']))
            current = current['next']
    records.sort(key=lambda x: x[0])
    return records

def bst_insert(root, name, phone):
    
    new_node = {'name': name, 'phone': phone, 'left': None, 'right': None}
    
    if root is None:
        return new_node
    
    current = root
    while True:
        if name < current['name']:
            if current['left'] is None:
                current['left'] = new_node
                break
            current = current['left']
        elif name > current['name']:
            if current['right'] is None:
                current['right'] = new_node
                break
            current = current['right']
        else:
            current['phone'] = phone
            break
    
    return root


def bst_find(root, name):
    
    current = root
    while current is not None:
        if name == current['name']:
            return current['phone']
        elif name < current['name']:
            current = current['left']
        else:
            current = current['right']
    return None


def _bst_find_min(node):
    
    current = node
    while current['left'] is not None:
        current = current['left']
    return current


def bst_delete(root, name):
    
    if root is None:
        return None
    
    parent = None
    current = root
    
    while current is not None and current['name'] != name:
        parent = current
        if name < current['name']:
            current = current['left']
        else:
            current = current['right']
    
    if current is None:  
        return root
    
    if current['left'] is None and current['right'] is None:
        if parent is None:
            return None
        if parent['left'] == current:
            parent['left'] = None
        else:
            parent['right'] = None
        return root
    
    if current['left'] is None:
        child = current['right']
    elif current['right'] is None:
        child = current['left']
    else:
        successor_parent = current
        successor = current['right']
        while successor['left'] is not None:
            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 root
    
    if parent is None:
        return child
    if parent['left'] == current:
        parent['left'] = child
    else:
        parent['right'] = child
    
    return root


def bst_list_all(root):
    records = []
    
    def inorder(node):
        if node is None:
            return
        inorder(node['left'])
        records.append((node['name'], node['phone']))
        inorder(node['right'])
    
    inorder(root)
    return records