From 089b6906b982b9c5bb4154f8939055386271212b Mon Sep 17 00:00:00 2001 From: SolovevDD Date: Sat, 28 Feb 2026 00:29:13 +0300 Subject: [PATCH 1/5] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=201.1.=D0=A1=D0=B2=D1=8F=D0=B7=D0=B0=D0=BD=D1=8B=D0=B9=20?= =?UTF-8?q?=D1=81=D0=BF=D0=B8=D1=81=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SolovevDD/zadanie11.py | 70 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 SolovevDD/zadanie11.py diff --git a/SolovevDD/zadanie11.py b/SolovevDD/zadanie11.py new file mode 100644 index 0000000..7465463 --- /dev/null +++ b/SolovevDD/zadanie11.py @@ -0,0 +1,70 @@ +def ll_insert(head, name, phone): + if head is None: + return {'name': name, 'phone': phone, 'next': None} + + curr = head + while True: + if curr['name'] == name: + curr['phone'] = phone + return head + + if curr['next'] is None: + break + + curr = curr['next'] + + curr['next'] = {'name': name, 'phone': phone, 'next': None} + return head + +def ll_find(head, name): + curr = head + while curr is not None: + if curr['name'] == name: + return curr['phone'] + curr = curr['next'] + return None + +def ll_delete(head, name): + if head is None: + return None + + if head['name'] == name: + return head['next'] + + curr = head + while curr['next'] is not None: + if curr['next']['name'] == name: + curr['next'] = curr['next']['next'] + return head + curr = curr['next'] + + return head + +def ll_list_all(head): + res = [] + curr = head + while curr is not None: + res.append((curr['name'], curr['phone'])) + curr = curr['next'] + + res.sort(key=lambda x: x[0]) + return res + +if __name__ == "__main__": + book = None + + book = ll_insert(book, "Маша", "8900111") + book = ll_insert(book, "Саша", "8900222") + book = ll_insert(book, "Даша", "8900333") + + print(ll_list_all(book)) + + book = ll_insert(book, "Маша", "0000000") + print(ll_list_all(book)) + + print(ll_find(book, "Саша")) + print(ll_find(book, "Петя")) + + book = ll_delete(book, "Маша") + book = ll_delete(book, "Саша") + print(ll_list_all(book)) \ No newline at end of file -- 2.43.0 From 82f0fc13e9d8c31cf6c5b784f581a273b5ead986 Mon Sep 17 00:00:00 2001 From: SolovevDD Date: Mon, 18 May 2026 19:32:30 +0300 Subject: [PATCH 2/5] [1] 1-st exersize LinkedListPhoneBook --- .../data/1-st exersize/LinkedListPhoneBook.py | 233 ++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 SolovevDD/docs/data/1-st exersize/LinkedListPhoneBook.py diff --git a/SolovevDD/docs/data/1-st exersize/LinkedListPhoneBook.py b/SolovevDD/docs/data/1-st exersize/LinkedListPhoneBook.py new file mode 100644 index 0000000..fa3afac --- /dev/null +++ b/SolovevDD/docs/data/1-st exersize/LinkedListPhoneBook.py @@ -0,0 +1,233 @@ +import time +import random +import csv +import os +import matplotlib.pyplot as plt + +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']: + current = current['next'] + current['next'] = new_node + return head + +def ll_find(head, name): + current = head + while current: + 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']: + if current['next']['name'] == name: + current['next'] = current['next']['next'] + return head + current = current['next'] + return head + +def ll_list_all(head): + result = [] + current = head + while current: + result.append((current['name'], current['phone'])) + current = current['next'] + return sorted(result) + +def create_hash_table(size=200): + return [None] * size + +def ht_insert(buckets, name, phone): + index = hash(name) % len(buckets) + buckets[index] = ll_insert(buckets[index], name, phone) + +def ht_find(buckets, name): + index = hash(name) % len(buckets) + return ll_find(buckets[index], name) + +def ht_delete(buckets, name): + index = hash(name) % len(buckets) + buckets[index] = ll_delete(buckets[index], name) + +def ht_list_all(buckets): + result = [] + for bucket in buckets: + current = bucket + while current: + result.append((current['name'], current['phone'])) + current = current['next'] + return sorted(result) + + +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 + return root + current = current['left'] + elif name > current['name']: + if current['right'] is None: + current['right'] = new_node + return root + current = current['right'] + else: + current['phone'] = phone + return root + + +def bst_find(root, name): + current = root + while current: + if name == current['name']: + return current['phone'] + elif name < current['name']: + current = current['left'] + else: + current = current['right'] + return None + + +def bst_delete(root, name): + if root is None: + return None + + parent = None + current = root + while current 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 or current['right'] is None: + child = current['left'] if current['left'] else current['right'] + if parent is None: + return child + if parent['left'] == current: + parent['left'] = child + else: + parent['right'] = child + else: + parent_min = current + min_node = current['right'] + while min_node['left']: + parent_min = min_node + min_node = min_node['left'] + + current['name'] = min_node['name'] + current['phone'] = min_node['phone'] + + if parent_min['left'] == min_node: + parent_min['left'] = min_node['right'] + else: + parent_min['right'] = min_node['right'] + + return root + + +def bst_list_all(root): + result = [] + def inorder(node): + if node: + inorder(node['left']) + result.append((node['name'], node['phone'])) + inorder(node['right']) + inorder(root) + return result + + +def generate_records(n=10000): + records = [(f"User_{i:05d}", f"8{random.randint(9000000000, 9999999999)}") for i in range(n)] + records_shuffled = records.copy() + random.shuffle(records_shuffled) + records_sorted = sorted(records, key=lambda x: x[0]) + return records_shuffled, records_sorted + + +def run_experiments(): + random.seed(42) + records_shuffled, records_sorted = generate_records(10000) + all_results = [] + + structures = ["LinkedList", "HashTable", "BST"] + modes = [("случайный", records_shuffled), ("отсортированный", records_sorted)] + + for mode_name, records in modes: + for struct_name in structures: + print(f"Тестируем: {struct_name} | Режим: {mode_name}") + + for run in range(5): + if struct_name == "LinkedList": + data = None + elif struct_name == "HashTable": + data = create_hash_table(200) + else: + data = None + + start = time.perf_counter() + for name, phone in records: + if struct_name == "LinkedList": + data = ll_insert(data, name, phone) + elif struct_name == "HashTable": + ht_insert(data, name, phone) + else: + data = bst_insert(data, name, phone) + insert_time = time.perf_counter() - start + + test_names = [r[0] for r in random.sample(records, 100)] + test_names += [f"None_{i}" for i in range(10)] + start = time.perf_counter() + for name in test_names: + if struct_name == "LinkedList": + ll_find(data, name) + elif struct_name == "HashTable": + ht_find(data, name) + else: + bst_find(data, name) + find_time = time.perf_counter() - start + + delete_names = [r[0] for r in random.sample(records, 50)] + start = time.perf_counter() + for name in delete_names: + if struct_name == "LinkedList": + data = ll_delete(data, name) + elif struct_name == "HashTable": + ht_delete(data, name) + else: + data = bst_delete(data, name) + delete_time = time.perf_counter() - start + + all_results.append([struct_name, mode_name, "вставка", run + 1, insert_time]) + all_results.append([struct_name, mode_name, "поиск", run + 1, find_time]) + all_results.append([struct_name, mode_name, "удаление", run + 1, delete_time]) + + os.makedirs("docs/data", exist_ok=True) + filepath = "docs/data/results.csv" + with open(filepath, "w", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerow(["Структура", "Режим", "Операция", "Запуск", "Время (сек)"]) + writer.writerows(all_results) + + print(f"\nРезультаты сохранены в {filepath}") + return all_results + -- 2.43.0 From fd110e41934983e516522cffed041368964da4ca Mon Sep 17 00:00:00 2001 From: SolovevDD Date: Mon, 18 May 2026 19:50:44 +0300 Subject: [PATCH 3/5] [1] 1-st exersize LinkedListPhoneBook --- SolovevDD/zadanie11.py | 70 ------------------------------------------ 1 file changed, 70 deletions(-) delete mode 100644 SolovevDD/zadanie11.py diff --git a/SolovevDD/zadanie11.py b/SolovevDD/zadanie11.py deleted file mode 100644 index 7465463..0000000 --- a/SolovevDD/zadanie11.py +++ /dev/null @@ -1,70 +0,0 @@ -def ll_insert(head, name, phone): - if head is None: - return {'name': name, 'phone': phone, 'next': None} - - curr = head - while True: - if curr['name'] == name: - curr['phone'] = phone - return head - - if curr['next'] is None: - break - - curr = curr['next'] - - curr['next'] = {'name': name, 'phone': phone, 'next': None} - return head - -def ll_find(head, name): - curr = head - while curr is not None: - if curr['name'] == name: - return curr['phone'] - curr = curr['next'] - return None - -def ll_delete(head, name): - if head is None: - return None - - if head['name'] == name: - return head['next'] - - curr = head - while curr['next'] is not None: - if curr['next']['name'] == name: - curr['next'] = curr['next']['next'] - return head - curr = curr['next'] - - return head - -def ll_list_all(head): - res = [] - curr = head - while curr is not None: - res.append((curr['name'], curr['phone'])) - curr = curr['next'] - - res.sort(key=lambda x: x[0]) - return res - -if __name__ == "__main__": - book = None - - book = ll_insert(book, "Маша", "8900111") - book = ll_insert(book, "Саша", "8900222") - book = ll_insert(book, "Даша", "8900333") - - print(ll_list_all(book)) - - book = ll_insert(book, "Маша", "0000000") - print(ll_list_all(book)) - - print(ll_find(book, "Саша")) - print(ll_find(book, "Петя")) - - book = ll_delete(book, "Маша") - book = ll_delete(book, "Саша") - print(ll_list_all(book)) \ No newline at end of file -- 2.43.0 From 4f28fd2015381f20c5433879f8363bb85a354ea6 Mon Sep 17 00:00:00 2001 From: SolovevDD Date: Mon, 18 May 2026 19:54:47 +0300 Subject: [PATCH 4/5] [1] 1-st exersize LinkedListPhoneBook --- .../data/1-st exersize/LinkedListPhoneBook.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/SolovevDD/docs/data/1-st exersize/LinkedListPhoneBook.py b/SolovevDD/docs/data/1-st exersize/LinkedListPhoneBook.py index fa3afac..0cb7da5 100644 --- a/SolovevDD/docs/data/1-st exersize/LinkedListPhoneBook.py +++ b/SolovevDD/docs/data/1-st exersize/LinkedListPhoneBook.py @@ -230,4 +230,29 @@ def run_experiments(): print(f"\nРезультаты сохранены в {filepath}") return all_results + + def plot_results(csv_path="docs/data/results.csv"): + import pandas as pd + df = pd.read_csv(csv_path) + summary = df.groupby(["Структура", "Режим", "Операция"])["Время (сек)"].mean().reset_index() + for op in ["вставка", "поиск", "удаление"]: + op_data = summary[summary["Операция"] == op] + plt.figure(figsize=(10, 6)) + x_labels = [] + y_values = [] + for _, row in op_data.iterrows(): + label = f"{row['Структура']}\n({row['Режим']})" + x_labels.append(label) + y_values.append(row["Время (сек)"]) + plt.bar(x_labels, y_values, color=['#4C72B0', '#55A868', '#C44E52'] * 2) + plt.title(f"Среднее время операции: {op}") + plt.ylabel("Время (сек)") + plt.xticks(rotation=45) + plt.tight_layout() + plt.savefig(f"docs/data/graph_{op}.png") + print(f"График сохранён: docs/data/graph_{op}.png") + +if __name__ == "__main__": + run_experiments() + plot_results() \ No newline at end of file -- 2.43.0 From 27865cf7d4b6c67fab7201d009922a6e9dd6b335 Mon Sep 17 00:00:00 2001 From: SolovevDD Date: Mon, 18 May 2026 20:05:09 +0300 Subject: [PATCH 5/5] [2] report for 1-st exersize --- .../1-st exersize/report_for_1-st_exersize.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 SolovevDD/docs/data/1-st exersize/report_for_1-st_exersize.py diff --git a/SolovevDD/docs/data/1-st exersize/report_for_1-st_exersize.py b/SolovevDD/docs/data/1-st exersize/report_for_1-st_exersize.py new file mode 100644 index 0000000..f237164 --- /dev/null +++ b/SolovevDD/docs/data/1-st exersize/report_for_1-st_exersize.py @@ -0,0 +1,35 @@ +ОТЧЁТ ПО ЗАДАНИЮ 1 + +1. Влияние порядка данных на BST +При случайном порядке данных BST работает быстро (вставка ~0.005 сек). +При отсортированном порядке дерево вырождается в цепочку, и время вставки +возрастает примерно в 50–60 раз (~0.31 сек). Сложность деградирует с O(log n) до O(n). + +2. Почему хеш-таблица нечувствительна к порядку +Хеш-таблица использует хеш-функцию, которая равномерно распределяет элементы +по бакетам. Поэтому порядок входных данных почти не влияет на скорость +вставки, поиска и удаления (в среднем O(1)). + +3. Почему связный список медленен при поиске +Для поиска в связном списке нужно последовательно пройти все элементы. +Поэтому поиск всегда выполняется за O(n), независимо от порядка данных. +Это делает его самым медленным при операциях поиска и удаления. + +4. Как работает удаление +- LinkedList: O(n) — нужно найти элемент и перестроить ссылки. +- HashTable: O(1) в среднем — удаление внутри нужного бакета. +- BST: O(log n) в среднем, O(n) в худшем — при двух потомках ищется + минимальный элемент в правом поддереве. + +5. Вывод и рекомендации + +Рекомендуемые структуры в зависимости от задачи: + +- Частые вставки и поиск → HashTable (лучшая общая производительность) +- Нужно получать данные в отсортированном порядке → BST (только при случайных данных) +- Данные приходят отсортированными → HashTable (BST сильно деградирует) +- Малый объём данных и простота → LinkedList + +Итог: Для большинства реальных задач лучше всего подходит хеш-таблица. +BST имеет смысл использовать только при случайном порядке данных и +необходимости частого получения отсортированного списка. \ No newline at end of file -- 2.43.0