Hasli4

Untitled

Jun 13th, 2025
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.53 KB | None | 0 0
  1. import re
  2.  
  3. INPUT_FILE = 'input.txt'
  4.  
  5. class Node:
  6. """Узел двоичного дерева, умеет строиться по «коду пути»."""
  7. def __init__(self, data=None):
  8. self.data = data
  9. self.left = None
  10. self.right = None
  11.  
  12. def ensure_path(self, code, prompt_intermediate: bool, prompt_final: bool, final_value=None):
  13. """
  14. Спускается от self по коду '0'/'1'. Если необходимый child is None:
  15. - для промежуточных позиций (не последний символ):
  16. если prompt_intermediate=True → спрашиваем, иначе создаём пустой;
  17. - для последнего символа:
  18. если prompt_final=True → спрашиваем,
  19. else (prompt_final=False) → создаём пустой.
  20. В конце, если final_value не None, записывает его в node.data.
  21. """
  22. node = self
  23. length = len(code)
  24. for i, c in enumerate(code):
  25. last = (i == length - 1)
  26. branch = 'left' if c == '0' else 'right'
  27. child = getattr(node, branch)
  28. if child is None:
  29. # решить, спрашивать ли у пользователя
  30. need_prompt = (not last and prompt_intermediate) or (last and prompt_final)
  31. if need_prompt:
  32. while True:
  33. text = input(
  34. f"Введите целое для {'промежуточного' if not last else 'конечного'} "
  35. f"узла '{code[:i+1]}' (от '{code[:i]}'): "
  36. ).strip()
  37. if text.isdigit():
  38. child = Node(int(text))
  39. break
  40. print("Ошибка: нужно целое неотрицательное число.")
  41. else:
  42. child = Node()
  43. setattr(node, branch, child)
  44. node = child
  45.  
  46. if final_value is not None:
  47. node.data = final_value
  48. return node
  49.  
  50. def insert_from_file(self):
  51. """
  52. Читает весь INPUT_FILE, собирает (number, code), сортирует по длине кода,
  53. затем для каждой пары: ensure_path(..., prompt_intermediate=True, prompt_final=False, final_value=number).
  54. """
  55. entries = []
  56. try:
  57. with open(INPUT_FILE, 'r', encoding='utf-8') as f:
  58. for lineno, line in enumerate(f, 1):
  59. text = line.strip()
  60. if not text: continue
  61. parts = text.split()
  62. if len(parts) != 2 or not parts[0].isdigit() or any(ch not in '01' for ch in parts[1]):
  63. print(f"[Строка {lineno}] Пропущена: ожидается '<число> <код>'.")
  64. continue
  65. entries.append((int(parts[0]), parts[1]))
  66. except FileNotFoundError:
  67. print(f"Ошибка: файл '{INPUT_FILE}' не найден.")
  68. exit(1)
  69.  
  70. entries.sort(key=lambda x: len(x[1]))
  71. for number, code in entries:
  72. node = self.ensure_path(
  73. code,
  74. prompt_intermediate=True, # спрашиваем только промежуточные
  75. prompt_final=False, # НЕ спрашиваем конечный
  76. final_value=number # сразу записываем из файла
  77. )
  78. # если тут node.data уже не равно number → был конфликт
  79. if node.data != number:
  80. print(f"[Код '{code}'] узел уже = {node.data}, пропуск {number}.")
  81.  
  82. def insert_manually(self):
  83. """
  84. Сначала собираем список вводимых пар, затем строим дерево точно так же,
  85. но конечный узел НЕ спрашиваем (prompt_final=False), поскольку пользователь ввёл его сам.
  86. """
  87. entries = []
  88. print("Ручной ввод. Формат: <число> <код 0/1>, 'q' — выход.")
  89. while True:
  90. s = input("> ").strip()
  91. if s.lower() == 'q': break
  92. parts = s.split()
  93. if len(parts)!=2 or not parts[0].isdigit() or any(ch not in '01' for ch in parts[1]):
  94. print("Неверный формат, повторите.")
  95. continue
  96. entries.append((int(parts[0]), parts[1]))
  97.  
  98. entries.sort(key=lambda x: len(x[1]))
  99. for number, code in entries:
  100. node = self.ensure_path(
  101. code,
  102. prompt_intermediate=True, # спрашиваем промежуточные
  103. prompt_final=False, # НЕ спрашиваем конечный
  104. final_value=number # записываем введённое число
  105. )
  106. if node.data != number:
  107. print(f"[Код '{code}'] узел уже = {node.data}, пропуск {number}.")
  108.  
  109. def collect(self, path="", out=None):
  110. """Собирает [(код_пути, data), ...] всех узлов."""
  111. if out is None: out = []
  112. out.append((path, self.data))
  113. if self.left: self.left.collect(path + "0", out)
  114. if self.right: self.right.collect(path + "1", out)
  115. return out
  116.  
  117. def print_tree(self, level=0):
  118. """Рисует дерево «на боку»: правые дети — сверху."""
  119. if self.right: self.right.print_tree(level+1)
  120. print(" "*level + f"-> {self.data}")
  121. if self.left: self.left.print_tree(level+1)
  122.  
  123.  
  124. # ==== Запуск ====
  125. print("=== Построение двоичного дерева по кодам путей ===")
  126. mode = input("1 — из файла, 2 — вручную: ").strip()
  127. root = Node(0)
  128.  
  129. if mode == '1':
  130. root.insert_from_file()
  131. else:
  132. root.insert_manually()
  133.  
  134. print("\nСписок узлов (код путь : значение):")
  135. for path, val in root.collect():
  136. print(f"{path or 'root':>5} : {val}")
  137.  
  138. print("\nГоризонтальное представление дерева:")
  139. root.print_tree()
  140.  
Advertisement
Add Comment
Please, Sign In to add comment