Hasli4

Untitled

Jun 13th, 2025
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.31 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'. На каждом шаге:
  15. - если узел отсутствует:
  16. • если это НЕ последний символ (промежуточный) и prompt_intermediate=True → спрашиваем у пользователя
  17. • если это последний символ и prompt_final=True → спрашиваем у пользователя
  18. • иначе создаём пустой узел автоматически
  19. В конце, если final_value задан (не None), присваиваем node.data = final_value.
  20. Возвращает получившийся узел.
  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"Введите целое неотрицательное для узла '{code[:i+1]}' "
  35. f"({'промежуточный' if not last else 'конечный'}) : "
  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. # если нам передали конкретное значение финального узла — записать
  47. if final_value is not None:
  48. node.data = final_value
  49. return node
  50.  
  51. def insert_from_file(self):
  52. """
  53. Считываем весь INPUT_FILE → собираем все (number, code) в список → сортируем по len(code) →
  54. затем для каждой пары вызываем ensure_path(code, prompt_intermediate=True, prompt_final=False, final_value=number).
  55. """
  56. entries = []
  57. try:
  58. with open(INPUT_FILE, 'r', encoding='utf-8') as f:
  59. for lineno, line in enumerate(f, 1):
  60. text = line.strip()
  61. if not text:
  62. continue
  63. parts = text.split()
  64. if len(parts) != 2 or not parts[0].isdigit() or any(ch not in '01' for ch in parts[1]):
  65. print(f"[Строка {lineno}] Пропущена: ожидался '<число> <код_пути>'.")
  66. continue
  67. entries.append((int(parts[0]), parts[1]))
  68. except FileNotFoundError:
  69. print(f"Ошибка: файл '{INPUT_FILE}' не найден.")
  70. exit(1)
  71.  
  72. # Сортируем по длине кода (чтобы предки создавались до потомков)
  73. entries.sort(key=lambda x: len(x[1]))
  74.  
  75. for number, code in entries:
  76. node = self.ensure_path(
  77. code,
  78. prompt_intermediate=True,
  79. prompt_final=False,
  80. final_value=number
  81. )
  82. # если узел уже имел data (каким-то образом) — предупреждаем
  83. if node.data != number:
  84. # если node.data был None, мы записали number → всё ок.
  85. # иначе (node.data != None и != number) — был конфликт.
  86. if node.data is not None:
  87. print(f"[Код '{code}'] Узел уже = {node.data}, пропущена запись {number}.")
  88.  
  89. def insert_manually(self):
  90. """
  91. Сначала собираем все пары в список, пока пользователь не введёт 'q'.
  92. Затем сортируем по len(code) и вызываем ensure_path(...) с prompt_intermediate=True, prompt_final=True.
  93. """
  94. entries = []
  95. print("Ручной ввод. По строкам: <число> <код_пути из 0/1>, или 'q' для конца.")
  96. while True:
  97. s = input("> ").strip()
  98. if s.lower() == 'q':
  99. break
  100. parts = s.split()
  101. if len(parts) != 2 or not parts[0].isdigit() or any(ch not in '01' for ch in parts[1]):
  102. print("Неверный формат, повторите.")
  103. continue
  104. entries.append((int(parts[0]), parts[1]))
  105.  
  106. # сортируем и строим
  107. entries.sort(key=lambda x: len(x[1]))
  108. for number, code in entries:
  109. node = self.ensure_path(
  110. code,
  111. prompt_intermediate=True,
  112. prompt_final=True,
  113. final_value=number
  114. )
  115. if node.data != number:
  116. print(f"[Код '{code}'] Узел уже = {node.data}, пропуск {number}.")
  117.  
  118. def collect(self, path="", out=None):
  119. """Рекурсивно собирает [(код_пути, data), ...] всех узлов."""
  120. if out is None:
  121. out = []
  122. out.append((path, self.data))
  123. if self.left:
  124. self.left.collect(path + "0", out)
  125. if self.right:
  126. self.right.collect(path + "1", out)
  127. return out
  128.  
  129. def print_tree(self, level=0):
  130. """Рисует дерево «на боку»: правые дети — выше, левые — ниже."""
  131. if self.right:
  132. self.right.print_tree(level + 1)
  133. print(" " * level + f"-> {self.data}")
  134. if self.left:
  135. self.left.print_tree(level + 1)
  136.  
  137.  
  138. # ==== Основной запуск ====
  139.  
  140. print("=== Построение двоичного дерева по кодам путей ===")
  141. mode = input("Выберите режим: 1 — из файла, 2 — вручную: ").strip()
  142. root = Node(0) # по условию корень сразу содержит 0
  143.  
  144. if mode == '1':
  145. root.insert_from_file()
  146. else:
  147. root.insert_manually()
  148.  
  149. print("\nСписок всех узлов (код путь : значение):")
  150. for path, val in root.collect():
  151. label = path or "root"
  152. print(f"{label:>5} : {val}")
  153.  
  154. print("\nГоризонтальное представление дерева:")
  155. root.print_tree()
  156.  
Advertisement
Add Comment
Please, Sign In to add comment