"""Телефонный справочник на трёх структурах данных.""" def _node(name, phone, next_node=None): return {"name": name, "phone": phone, "next": next_node} def ll_insert(head, name, phone): """Добавить запись в конец списка или обновить существующую.""" if head is None: return _node(name, phone) current = head while True: if current["name"] == name: current["phone"] = phone return head if current["next"] is None: current["next"] = _node(name, phone) return head current = current["next"] 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"] previous, current = head, head["next"] while current is not None: if current["name"] == name: previous["next"] = current["next"] break previous, current = 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"] return sorted(records, key=lambda record: record[0]) def _require_buckets(buckets): if not buckets: raise ValueError("Хеш-таблица должна содержать хотя бы один бакет") def _hash_index(name, bucket_count): """Хеш-функция.""" value = 0 for character in name: value = (value * 31 + ord(character)) % bucket_count return value def ht_insert(buckets, name, phone): _require_buckets(buckets) index = _hash_index(name, len(buckets)) buckets[index] = ll_insert(buckets[index], name, phone) def ht_find(buckets, name): _require_buckets(buckets) return ll_find(buckets[_hash_index(name, len(buckets))], name) def ht_delete(buckets, name): _require_buckets(buckets) index = _hash_index(name, len(buckets)) buckets[index] = ll_delete(buckets[index], name) def ht_list_all(buckets): _require_buckets(buckets) records = [] for head in buckets: records.extend(ll_list_all(head)) return sorted(records, key=lambda record: record[0]) def _bst_node(name, phone): return {"name": name, "phone": phone, "left": None, "right": None} def bst_insert(root, name, phone): if root is None: return _bst_node(name, phone) current = root while True: if name == current["name"]: current["phone"] = phone return root side = "left" if name < current["name"] else "right" if current[side] is None: current[side] = _bst_node(name, phone) return root current = current[side] def bst_find(root, name): current = root while current is not None: if name == current["name"]: return current["phone"] current = current["left"] if name < current["name"] else current["right"] return None def bst_delete(root, name): parent = None current = root while current is not None and current["name"] != name: parent = current current = current["left"] if name < current["name"] else current["right"] if current is None: return root if current["left"] is not None and current["right"] is not None: successor_parent = current successor = current["right"] while successor["left"] is not None: successor_parent = successor successor = successor["left"] current["name"], current["phone"] = successor["name"], successor["phone"] parent, current = successor_parent, successor child = current["left"] if current["left"] is not None else current["right"] if parent is None: return child if parent["left"] is current: parent["left"] = child else: parent["right"] = child return root def bst_list_all(root): records, stack = [], [] current = root while stack or current is not None: while current is not None: stack.append(current) current = current["left"] current = stack.pop() records.append((current["name"], current["phone"])) current = current["right"] return records