diff --git a/sorokinfi/427.md b/sorokinfi/427.md deleted file mode 100644 index e69de29b..00000000 diff --git a/sorokinfi/427.py b/sorokinfi/427.py new file mode 100644 index 00000000..8a00d895 --- /dev/null +++ b/sorokinfi/427.py @@ -0,0 +1,572 @@ +import csv +import random +import sys +import time +from collections import defaultdict, deque +import pandas as pd +import matplotlib.pyplot as plt +from abc import ABC, abstractmethod +import os + +current_dir = os.path.dirname(os.path.abspath(__file__)) +os.chdir(current_dir) + +# увеличиваем лимит рекурсии +sys.setrecursionlimit(25000) + +# ЗАДАНИЕ 1: СТРУКТУРЫ ДАННЫХ + +# 1. связный список, узел: {'name': 'Имя', 'phone': '123', 'next': None} + +# проходит до конца и добавляет в конец +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 + +# ищет узел, возвращает телефон или None +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 + + +# 2. хеш-таблица + +# хеш-функция для вычисления бекета +def ht_hash(name, size): + return hash(name) % size + +# вычисляет индекс, вызывает ll_insert для соответствующего бакета +def ht_insert(buckets, name, phone): + size = len(buckets) + idx = ht_hash(name, size) + buckets[idx] = ll_insert(buckets[idx], name, phone) + +# поиск по хеш-таблице +def ht_find(buckets, name): + size = len(buckets) + idx = ht_hash(name, size) + return ll_find(buckets[idx], name) + +# удаление из хеш-таблицы +def ht_delete(buckets, name): + size = len(buckets) + idx = ht_hash(name, size) + buckets[idx] = ll_delete(buckets[idx], name) + +# собирает все записи из всех бакетов и сортирует +def ht_list_all(buckets): + all_records = [] + for head in buckets: + current = head + while current is not None: + all_records.append((current['name'], current['phone'])) + current = current['next'] + all_records.sort(key=lambda x: x[0]) + return all_records + + +# 3. двоичное дерево поиска +# узел — словарь: {'name': 'Имя', 'phone': '123', 'left': None, 'right': None} + +# рекурсивно или итеративно вставляет, возвращает новый корень (если корень меняется) +def bst_insert(root, name, phone): + if root is None: + return {'name': name, 'phone': phone, 'left': None, 'right': None} + + if name < root['name']: + root['left'] = bst_insert(root['left'], name, phone) + elif name > root['name']: + root['right'] = bst_insert(root['right'], name, phone) + else: + root['phone'] = phone + return root + +# поиск +def bst_find(root, name): + if root is None: + return None + if name == root['name']: + return root['phone'] + elif name < root['name']: + return bst_find(root['left'], name) + else: + return bst_find(root['right'], name) + +# удаление, возвращает новый корень +def bst_delete(root, name): + if root is None: + return None + + if name < root['name']: + root['left'] = bst_delete(root['left'], name) + elif name > root['name']: + root['right'] = bst_delete(root['right'], name) + else: + # одна ветвь или её отсутствие + if root['left'] is None: + return root['right'] + if root['right'] is None: + return root['left'] + # две ветви + successor = root['right'] + while successor['left'] is not None: + successor = successor['left'] + + root['name'] = successor['name'] + root['phone'] = successor['phone'] + root['right'] = bst_delete(root['right'], successor['name']) + + return root + +# центрированный обход (рекурсивно собирает записи в отсортированном порядке) +def bst_list_all(root): + records = [] + def _inorder(node): + if node is not None: + _inorder(node['left']) + records.append((node['name'], node['phone'])) + _inorder(node['right']) + _inorder(root) + return records + + +# 4. ЭКСПЕРИМЕНТАЛЬНАЯ ЧАСТЬ + +def run_experiments(): + N = 3000 + HASH_SIZE = 1007 + + print(f"генерация тестовых данных для N = {N}...") + records_sorted = [(f"User_{i:05d}", f"+7999123{i:04d}") for i in range(N)] + records_shuffled = records_sorted.copy() + random.seed(42) + random.shuffle(records_shuffled) + + # подготовка выборок + existing_sample = [r[0] for r in random.sample(records_sorted, min(100, N))] + non_existing_sample = [f"None_{i}" for i in range(10)] + search_names = existing_sample + non_existing_sample + + delete_names = [r[0] for r in random.sample(records_sorted, min(50, N))] + csv_rows = [["структура", "режим", "операция", "повторение", "время (сек)"]] + modes = [("случайный", records_shuffled), ("отсортированный", records_sorted)] + + print("запуск экспериментов (5 повторений для каждого режима)") + +# ТЕСТ: СВЯЗНЫЙ СПИСОК + + for mode_name, data in modes: + for rep in range(1, 6): + head = None + t_start = time.perf_counter() + for name, phone in data: + head = ll_insert(head, name, phone) + t_end = time.perf_counter() + csv_rows.append(["LinkedList", mode_name, "вставка", rep, t_end - t_start]) + + t_start = time.perf_counter() + for name in search_names: + ll_find(head, name) + t_end = time.perf_counter() + csv_rows.append(["LinkedList", mode_name, "поиск", rep, t_end - t_start]) + + t_start = time.perf_counter() + for name in delete_names: + head = ll_delete(head, name) + t_end = time.perf_counter() + csv_rows.append(["LinkedList", mode_name, "удаление", rep, t_end - t_start]) + +# ТЕСТ: ХЕШ-ТАБЛИЦА + + for mode_name, data in modes: + for rep in range(1, 6): + buckets = [None] * HASH_SIZE + t_start = time.perf_counter() + for name, phone in data: + ht_insert(buckets, name, phone) + t_end = time.perf_counter() + csv_rows.append(["HashTable", mode_name, "вставка", rep, t_end - t_start]) + + t_start = time.perf_counter() + for name in search_names: + ht_find(buckets, name) + t_end = time.perf_counter() + csv_rows.append(["HashTable", mode_name, "поиск", rep, t_end - t_start]) + + t_start = time.perf_counter() + for name in delete_names: + ht_delete(buckets, name) + t_end = time.perf_counter() + csv_rows.append(["HashTable", mode_name, "удаление", rep, t_end - t_start]) + +# ТЕСТ: ДЕРЕВО ПОИСКА (BST) + + for mode_name, data in modes: + for rep in range(1, 6): + root = None + t_start = time.perf_counter() + for name, phone in data: + root = bst_insert(root, name, phone) + t_end = time.perf_counter() + csv_rows.append(["BST", mode_name, "вставка", rep, t_end - t_start]) + + t_start = time.perf_counter() + for name in search_names: + bst_find(root, name) + t_end = time.perf_counter() + csv_rows.append(["BST", mode_name, "поиск", rep, t_end - t_start]) + + t_start = time.perf_counter() + for name in delete_names: + root = bst_delete(root, name) + t_end = time.perf_counter() + csv_rows.append(["BST", mode_name, "удаление", rep, t_end - t_start]) + +# сохранение в csv + with open("results.csv", "w", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerows(csv_rows) + print("\nвсе замеры сохранены в файл 'results.csv'.") + + show_summary(csv_rows) + +# функция для подсчета и вывода среднего времени +def show_summary(rows): + summary = defaultdict(list) + for row in rows[1:]: + struct, mode, op, rep, elapsed = row + summary[(struct, mode, op)].append(elapsed) + + print("\nСВОДНЫЕ РЕЗУЛЬТАТЫ (СРЕДНЕЕ ВРЕМЯ ИЗ 5 ЗАПУСКОВ)") + print(f"{'структура':<12} | {'режим данных':<15} | {'операция':<10} | {'время (сек)':<12}") + print("-" * 59) + for (struct, mode, op), times in sorted(summary.items()): + avg_time = sum(times) / len(times) + print(f"{struct:<12} | {mode:<15} | {op:<10} | {avg_time:.6f}") + + + +# 5. АНАЛИЗ РЕЗУЛЬТАТОВ + +def plot_results(csv_filename="results.csv"): + print("построение графика") + try: + df = pd.read_csv(csv_filename) + + df_insert = df[df["операция"] == "вставка"] + + pivot_df = df_insert.pivot_table( + index="структура", + columns="режим", + values="время (сек)", + aggfunc="mean" + ) + + pivot_df.plot(kind="bar", figsize=(10, 6), color=['#1f77b4', '#ff7f0e']) + + plt.title("сравнение времени вставки (N=3000)") + plt.ylabel("среднее время выполнения (сек)") + plt.xlabel("структура данных") + plt.xticks(rotation=0) + plt.grid(axis='y', linestyle='--', alpha=0.7) + plt.savefig("benchmark_chart.png") + print("график сохранен как benchmark_chart.png") + plt.show() + + except FileNotFoundError: + print(f"файл {csv_filename} не найден. сначала запустите тесты.") + + +def print_report(): + report = """ + + 5. АНАЛИЗ РЕЗУЛЬТАТОВ ЭКСПЕРИМЕНТОВ + +1. Влияние порядка входных данных на скорость вставки в BST: + - На случайных данных BST строится сбалансированным. Высота дерева составляет + примерно O(log N), поэтому вставка происходит почти мгновенно. + - На отсортированных данных происходит ДЕГРАДАЦИЯ дерева. Каждый элемент больше + предыдущего и вставляется строго вправо. Дерево вырождается в связный список. + Сложность возрастает до O(N), что отчетливо видно по гигантскому пику на графике. + +2. Чувствительность Хеш-таблицы к порядку: + - Хеш-таблица НЕ ЧУВСТВИТЕЛЬНА к порядку данных. Математическая хеш-функция + превращает любое имя в хаотичный индекс и равномерно распределяет записи + по бакетам. В обоих режимах операции выполняются за константное время O(1). + +3. Почему связный список всегда медленен при поиске: + - У связного списка нет индексов для прямого доступа. Поиск всегда линейный O(N) + — алгоритм вынужден последовательно перебирать элементы от головы к хвосту. + +4. Как удаление работает в каждой структуре: + - Связный список: O(N) затрачивается на линейный поиск узла, само удаление — O(1). + - Хеш-таблица: O(1) нахождение бакета по хешу, удаление из цепочки коллизий мгновенно. + - BST: В среднем O(log N), в худшем O(N). Требует поиска узла и перестройки связей + (замена удаляемого узла на его потомка или минимальный элемент правого поддерева). + +ВЫВОД: + - ДЛЯ ЧАСТЫХ ВСТАВОК И ПОИСКА: Идеально подходит Хеш-таблица благодаря скорости O(1). + - ДЛЯ ПОЛУЧЕНИЯ ДАННЫХ В ПОРЯДКЕ (АЛФАВИТНОМ): Стоит выбирать Двоичное дерево поиска + (BST), так как обход дерева (In-order traversal) сразу выдает отсортированные данные. + """ + print(report) + +def run_task_1(): + run_experiments() + plot_results() + print_report() + +# ЗАДАНИЕ 2: ПОИСК ВЫХОДА ИЗ ЛАБИРИНТА + +# поиск выхода из лабиринта +class Maze: + def __init__(self, grid): + self.grid = grid + self.rows = len(grid) + self.cols = len(grid[0]) if self.rows > 0 else 0 + self.start = self._find_point('S') + self.end = self._find_point('E') + + def _find_point(self, char): + for r in range(self.rows): + for c in range(self.cols): + if self.grid[r][c] == char: return (r, c) + return None + + def is_walkable(self, r, c): + return 0 <= r < self.rows and 0 <= c < self.cols and self.grid[r][c] != '#' + +class PathfindingStrategy(ABC): + @abstractmethod + def solve(self, maze: Maze): pass + + +# стратегия №1: BFS +class BFSStrategy(PathfindingStrategy): + def solve(self, maze: Maze): + + # проверка входных данных + if not maze.start or not maze.end: + return None, 0 + + # инициализация структур данных + queue = deque([(maze.start, [maze.start])]) + visited = set([maze.start]) + + # направление для шагов + directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] + + # основной цикл обхода лабиринта + while queue: + current, path = queue.popleft() + if current == maze.end: + return path, len(visited) # возвращаем путь и размер посещенных клеток + r, c = current + for dr, dc in directions: + nr, nc = r + dr, c + dc + if maze.is_walkable(nr, nc) and (nr, nc) not in visited: + visited.add((nr, nc)) + queue.append(((nr, nc), path + [(nr, nc)])) + return None, len(visited) + + +# стратегия №2: DFS +class DFSStrategy(PathfindingStrategy): + def solve(self, maze: Maze): + if not maze.start or not maze.end: + return None, 0 + + # инициализация структур данных + stack = [(maze.start, [maze.start])] + visited = set() + directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] + + # основной цикл обхода лабиринта + while stack: + current, path = stack.pop() + if current in visited: + continue + visited.add(current) + if current == maze.end: + return path, len(visited) + r, c = current + for dr, dc in directions: + nr, nc = r + dr, c + dc + if maze.is_walkable(nr, nc): + stack.append(((nr, nc), path + [(nr, nc)])) + return None, len(visited) + +class MazeSolver: + def __init__(self, strategy: PathfindingStrategy): self._strategy = strategy + def set_strategy(self, strategy: PathfindingStrategy): self._strategy = strategy + def solve_maze(self, maze: Maze): return self._strategy.solve(maze) + +# подготовка тестовых лабиринтов +class MazeFactory: + @staticmethod + def _generate_random_grid(width, height, wall_chance=0.25, has_exit=True): + # вспомогательный метод генерации сетки лабиринта заданной сложности + grid = [[" " for _ in range(width)] for _ in range(height)] + for r in range(height): + for c in range(width): + if random.random() < wall_chance: grid[r][c] = "#" + grid[0][0] = "S" + if has_exit: + grid[height-1][width-1] = "E" + else: + grid[height-1][width-1] = "E" + if height > 1: grid[height-1][width-2] = "#" + if width > 1: grid[height-2][width-1] = "#" + return grid + + @staticmethod + def create_maze(maze_type): + random.seed(42) + if maze_type == "маленький (10x10)": + return Maze(MazeFactory._generate_random_grid(10, 10, wall_chance=0.15)) + elif maze_type == "средний (50x50)": + return Maze(MazeFactory._generate_random_grid(50, 50, wall_chance=0.25)) + elif maze_type == "большой (100x100)": + return Maze(MazeFactory._generate_random_grid(100, 100, wall_chance=0.3)) + elif maze_type == "пустой": + grid = [[" " for _ in range(30)] for _ in range(30)] + grid[0][0], grid[29][29] = "S", "E" + return Maze(grid) + elif maze_type == "без выхода": + return Maze(MazeFactory._generate_random_grid(20, 20, wall_chance=0.2, has_exit=False)) + return None + +# экспериментальная часть лабиринтов +def run_maze_experiments(): + maze_types = ["маленький (10x10)", "средний (50x50)", "большой (100x100)", "пустой", "без выхода"] + strategies = [("BFS", BFSStrategy()), ("DFS", DFSStrategy())] + csv_rows = [["лабиринт", "стратегия", "время_мс", "посещено_клеток", "длина_пути"]] + + print("\nзапуск экспериментов(5 повторений)") + + for m_type in maze_types: + maze_obj = MazeFactory.create_maze(m_type) + for strat_name, strategy in strategies: + solver = MazeSolver(strategy) + + times = [] + visited_cells = 0 + path_len = 0 + + # запускаем по 5 раз для усреднения времени + for rep in range(5): + t_start = time.perf_counter() + path, visited = solver.solve_maze(maze_obj) + t_end = time.perf_counter() + + times.append((t_end - t_start) * 1000) # переводим в миллисекунды + visited_cells = visited + path_len = len(path) if path else 0 + + avg_time_ms = sum(times) / len(times) + csv_rows.append([m_type, strat_name, round(avg_time_ms, 4), visited_cells, path_len]) + + # сохраняем в CSV + with open("maze_results.csv", "w", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerows(csv_rows) + print("Результаты сохранены в 'maze_results.csv'") + + df = pd.DataFrame(csv_rows[1:], columns=csv_rows[0]) + print("\nТАБЛИЦА СРАВНЕНИЯ АЛГОРИТМОВ ПОИСКА:") + print(df.to_string(index=False)) + + # визуализация графиков + print("\nпостроение графиков эффективности") + for m_type in maze_types: + sub_df = df[df["лабиринт"] == m_type] + + fig, ax1 = plt.subplots(figsize=(7, 4)) + ax2 = ax1.twinx() + + sub_df.plot(kind="bar", x="стратегия", y="время_мс", ax=ax1, position=0, width=0.2, color="blue", legend=False) + sub_df.plot(kind="bar", x="стратегия", y="посещено_клеток", ax=ax2, position=1, width=0.2, color="orange", legend=False) + + ax1.set_ylabel("время выполнения (мс)", color="blue") + ax2.set_ylabel("посещено клеток (ед)", color="orange") + plt.title(f"эффективность на лабиринте: {m_type}") + ax1.set_xticklabels(sub_df["стратегия"], rotation=0) + + lines1, labels1 = ax1.get_legend_handles_labels() + lines2, labels2 = ax2.get_legend_handles_labels() + ax1.legend(lines1 + lines2, ["время (мс)", "посещено клеток"], loc="upper center") + + plt.tight_layout() + filename = f"maze_chart_{m_type.replace(' ', '_').replace('(', '').replace(')', '')}.png" + plt.savefig(filename) + plt.close() + print("графики для каждого типа лабиринта сохранены в текущую папку") + +def print_maze_report(): + print(""" + ВЫВОДЫ ПО ИТОГАМ АНАЛИЗА ЛАБИРИНТОВ: + 1. Маленький и Пустой лабиринты: Оба алгоритма работают мгновенно. Однако в пустом + пространстве BFS проверяет почти все клетки «волной» до достижения цели, в то время + как DFS может случайно угадать прямую траекторию быстрее, но выдать неоптимальный путь. + 2. Средний и Большой лабиринты (с тупиками): BFS стабильно находит самый КОРОТКИЙ путь, + однако тратит много памяти и времени на посещение клеток. DFS работает непредсказуемо, + его путь часто длиннее в разы, так как он «плутает» по тупикам. + 3. Лабиринт без выхода: Оба алгоритма вынуждены совершить полный перебор графа. + Количество посещенных клеток у них совпадает и равняется общему числу доступных клеток. + """) + +def run_task_2(): + run_maze_experiments() + print_maze_report() + +# главное меню + +def main(): + while True: + print("МЕНЮ ЛАБОРАТОРНЫХ РАБОТ") + print("1. Задание 1: структуры данных") + print("2. Задание 2: эксперименты с Лабиринтами") + print("0. Выход") + choice = input("Введите номер задания: ") + if choice == '1': run_task_1() + elif choice == '2': run_task_2() + elif choice == '0': break + else: print("Ошибка ввода.") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/sorokinfi/benchmark_chart.png b/sorokinfi/benchmark_chart.png new file mode 100644 index 00000000..ffbc48ae Binary files /dev/null and b/sorokinfi/benchmark_chart.png differ diff --git a/sorokinfi/maze_chart_без_выхода.png b/sorokinfi/maze_chart_без_выхода.png new file mode 100644 index 00000000..c2add769 Binary files /dev/null and b/sorokinfi/maze_chart_без_выхода.png differ diff --git a/sorokinfi/maze_chart_большой_100x100.png b/sorokinfi/maze_chart_большой_100x100.png new file mode 100644 index 00000000..2f4facf1 Binary files /dev/null and b/sorokinfi/maze_chart_большой_100x100.png differ diff --git a/sorokinfi/maze_chart_маленький_10x10.png b/sorokinfi/maze_chart_маленький_10x10.png new file mode 100644 index 00000000..b8be69a7 Binary files /dev/null and b/sorokinfi/maze_chart_маленький_10x10.png differ diff --git a/sorokinfi/maze_chart_пустой.png b/sorokinfi/maze_chart_пустой.png new file mode 100644 index 00000000..6d0be97c Binary files /dev/null and b/sorokinfi/maze_chart_пустой.png differ diff --git a/sorokinfi/maze_chart_средний_50x50.png b/sorokinfi/maze_chart_средний_50x50.png new file mode 100644 index 00000000..8d13ce64 Binary files /dev/null and b/sorokinfi/maze_chart_средний_50x50.png differ diff --git a/sorokinfi/maze_results.csv b/sorokinfi/maze_results.csv new file mode 100644 index 00000000..55f6aa44 --- /dev/null +++ b/sorokinfi/maze_results.csv @@ -0,0 +1,11 @@ +лабиринт,стратегия,время_мс,посещено_клеток,длина_пути +маленький (10x10),BFS,0.0895,85,19 +маленький (10x10),DFS,0.0553,42,41 +средний (50x50),BFS,0.0027,2,0 +средний (50x50),DFS,0.0023,2,0 +большой (100x100),BFS,0.0014,1,0 +большой (100x100),DFS,0.0011,1,0 +пустой,BFS,0.9422,900,59 +пустой,DFS,14.7181,871,871 +без выхода,BFS,0.3453,325,0 +без выхода,DFS,0.5775,325,0 diff --git a/sorokinfi/results.csv b/sorokinfi/results.csv new file mode 100644 index 00000000..b716cb4e --- /dev/null +++ b/sorokinfi/results.csv @@ -0,0 +1,91 @@ +структура,режим,операция,повторение,время (сек) +LinkedList,случайный,вставка,1,0.1129304999994929 +LinkedList,случайный,поиск,1,0.006587000003491994 +LinkedList,случайный,удаление,1,0.00433809999958612 +LinkedList,случайный,вставка,2,0.11600629999884404 +LinkedList,случайный,поиск,2,0.0070252999939839356 +LinkedList,случайный,удаление,2,0.0037247000000206754 +LinkedList,случайный,вставка,3,0.11695830000098795 +LinkedList,случайный,поиск,3,0.006697200005874038 +LinkedList,случайный,удаление,3,0.0038005000023986213 +LinkedList,случайный,вставка,4,0.11354900000151247 +LinkedList,случайный,поиск,4,0.007001000005402602 +LinkedList,случайный,удаление,4,0.003736999999091495 +LinkedList,случайный,вставка,5,0.11800010000297334 +LinkedList,случайный,поиск,5,0.006789500002923887 +LinkedList,случайный,удаление,5,0.003871599998092279 +LinkedList,отсортированный,вставка,1,0.11360589999821968 +LinkedList,отсортированный,поиск,1,0.005773999997472856 +LinkedList,отсортированный,удаление,1,0.004597200000716839 +LinkedList,отсортированный,вставка,2,0.11909130000276491 +LinkedList,отсортированный,поиск,2,0.006270099998801015 +LinkedList,отсортированный,удаление,2,0.00467449999996461 +LinkedList,отсортированный,вставка,3,0.11582009999983711 +LinkedList,отсортированный,поиск,3,0.006280699999479111 +LinkedList,отсортированный,удаление,3,0.004889000003458932 +LinkedList,отсортированный,вставка,4,0.11719879999873228 +LinkedList,отсортированный,поиск,4,0.006236399996851105 +LinkedList,отсортированный,удаление,4,0.004462299999431707 +LinkedList,отсортированный,вставка,5,0.12187409999751253 +LinkedList,отсортированный,поиск,5,0.006323499997961335 +LinkedList,отсортированный,удаление,5,0.004649099995731376 +HashTable,случайный,вставка,1,0.0012417999969329685 +HashTable,случайный,поиск,1,3.5099998058285564e-05 +HashTable,случайный,удаление,1,2.1699997887481004e-05 +HashTable,случайный,вставка,2,0.00101379999978235 +HashTable,случайный,поиск,2,3.1400006264448166e-05 +HashTable,случайный,удаление,2,1.799999881768599e-05 +HashTable,случайный,вставка,3,0.0009945999991032295 +HashTable,случайный,поиск,3,3.0999995942693204e-05 +HashTable,случайный,удаление,3,1.750000228639692e-05 +HashTable,случайный,вставка,4,0.0009932999964803457 +HashTable,случайный,поиск,4,2.9999995604157448e-05 +HashTable,случайный,удаление,4,1.7099999240599573e-05 +HashTable,случайный,вставка,5,0.0009849999987636693 +HashTable,случайный,поиск,5,3.089999518124387e-05 +HashTable,случайный,удаление,5,1.7300000763498247e-05 +HashTable,отсортированный,вставка,1,0.0010356999991927296 +HashTable,отсортированный,поиск,1,4.599999374477193e-05 +HashTable,отсортированный,удаление,1,2.2100000933278352e-05 +HashTable,отсортированный,вставка,2,0.0009875999967334792 +HashTable,отсортированный,поиск,2,3.090000245720148e-05 +HashTable,отсортированный,удаление,2,1.8399994587525725e-05 +HashTable,отсортированный,вставка,3,0.0009702000024844892 +HashTable,отсортированный,поиск,3,3.0300005164463073e-05 +HashTable,отсортированный,удаление,3,1.870000414783135e-05 +HashTable,отсортированный,вставка,4,0.001106600000639446 +HashTable,отсортированный,поиск,4,3.139999898849055e-05 +HashTable,отсортированный,удаление,4,1.8799997633323073e-05 +HashTable,отсортированный,вставка,5,0.0009694999971543439 +HashTable,отсортированный,поиск,5,3.060000017285347e-05 +HashTable,отсортированный,удаление,5,1.8200000340584666e-05 +BST,случайный,вставка,1,0.004694000002928078 +BST,случайный,поиск,1,0.00013359999866224825 +BST,случайный,удаление,1,8.38999985717237e-05 +BST,случайный,вставка,2,0.004346499998064246 +BST,случайный,поиск,2,0.0002164999968954362 +BST,случайный,удаление,2,0.00016500000492669642 +BST,случайный,вставка,3,0.004590399999869987 +BST,случайный,поиск,3,0.0001371000034851022 +BST,случайный,удаление,3,8.090000483207405e-05 +BST,случайный,вставка,4,0.004372099996544421 +BST,случайный,поиск,4,0.00012819999392377213 +BST,случайный,удаление,4,7.929999992484227e-05 +BST,случайный,вставка,5,0.004390299996885005 +BST,случайный,поиск,5,0.00013029999536229298 +BST,случайный,удаление,5,7.74000000092201e-05 +BST,отсортированный,вставка,1,0.7734344999989844 +BST,отсортированный,поиск,1,0.018798999997670762 +BST,отсортированный,удаление,1,0.01326369999878807 +BST,отсортированный,вставка,2,0.7684502999982215 +BST,отсортированный,поиск,2,0.019605599998612888 +BST,отсортированный,удаление,2,0.013238500003353693 +BST,отсортированный,вставка,3,0.7711517999996431 +BST,отсортированный,поиск,3,0.018355100000917446 +BST,отсортированный,удаление,3,0.012963099994522054 +BST,отсортированный,вставка,4,0.787827299995115 +BST,отсортированный,поиск,4,0.019717699993634596 +BST,отсортированный,удаление,4,0.013514999998733401 +BST,отсортированный,вставка,5,0.7936753000030876 +BST,отсортированный,поиск,5,0.019170500003383495 +BST,отсортированный,удаление,5,0.01344999999855645