2026-rff_mp/MininaVD/docs/data/Untitled8.ipynb
2026-05-16 18:08:27 +03:00

594 lines
25 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "code",
"execution_count": 3,
"id": "3701053f-41f9-464d-a44f-cbda38c1caf7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ЭКСПЕРИМЕНТАЛЬНОЕ СРАВНЕНИЕ СТРУКТУР ДАННЫХ\n",
"Телефонный справочник - 10000 записей\n",
"\n",
" Результаты будут сохранены в: C:\\Users\\weron\\experiment_results.csv\n",
" Сгенерировано 10000 записей\n",
"\n",
"2. Тестирование режима: случайный\n",
"\n",
" LINKED_LIST:\n",
" Вставка 10000 записей\n",
" Время: 9.2970 сек (среднее)\n",
" Поиск 110 записей\n",
" Время: 0.0946 сек (среднее)\n",
" Удаление 50 записей\n",
" Время: 0.0000 сек (среднее)\n",
"\n",
" HASH_TABLE:\n",
" Вставка 10000 записей\n",
" Время: 0.4810 сек (среднее)\n",
" Поиск 110 записей\n",
" Время: 0.0039 сек (среднее)\n",
" Удаление 50 записей\n",
" Время: 0.0030 сек (среднее)\n",
"\n",
" BST:\n",
" Вставка 10000 записей\n",
" Время: 0.0490 сек (среднее)\n",
" Поиск 110 записей\n",
" Время: 0.0004 сек (среднее)\n",
" Удаление 50 записей\n",
" Время: 0.1141 сек (среднее)\n",
"\n",
"2. Тестирование режима: отсортированный\n",
"\n",
" LINKED_LIST:\n",
" Вставка 10000 записей\n",
" Время: 9.2504 сек (среднее)\n",
" Поиск 110 записей\n",
" Время: 0.1115 сек (среднее)\n",
" Удаление 50 записей\n",
" Время: 0.0000 сек (среднее)\n",
"\n",
" HASH_TABLE:\n",
" Вставка 10000 записей\n",
" Время: 0.4928 сек (среднее)\n",
" Поиск 110 записей\n",
" Время: 0.0061 сек (среднее)\n",
" Удаление 50 записей\n",
" Время: 0.0029 сек (среднее)\n",
"\n",
" BST:\n",
" Вставка 10000 записей\n",
" Время: 22.1688 сек (среднее)\n",
" Поиск 110 записей\n",
" Время: 0.1297 сек (среднее)\n",
" Удаление 50 записей\n",
" Время: 0.1115 сек (среднее)\n",
"\n",
"3. Сохранение результатов\n",
" Результаты сохранены в: C:\\Users\\weron\\experiment_results.csv\n",
"СВОДНАЯ ТАБЛИЦА РЕЗУЛЬТАТОВ\n",
"Структура Режим Операция Среднее время (сек) \n",
"linked_list случайный вставка 9.296975 \n",
"linked_list случайный поиск 0.094569 \n",
"linked_list случайный удаление 0.000022 \n",
"hash_table случайный вставка 0.481027 \n",
"hash_table случайный поиск 0.003911 \n",
"hash_table случайный удаление 0.003046 \n",
"bst случайный вставка 0.049011 \n",
"bst случайный поиск 0.000368 \n",
"bst случайный удаление 0.114051 \n",
"linked_list отсортированный вставка 9.250436 \n",
"linked_list отсортированный поиск 0.111506 \n",
"linked_list отсортированный удаление 0.000018 \n",
"hash_table отсортированный вставка 0.492765 \n",
"hash_table отсортированный поиск 0.006051 \n",
"hash_table отсортированный удаление 0.002869 \n",
"bst отсортированный вставка 22.168779 \n",
"bst отсортированный поиск 0.129713 \n",
"bst отсортированный удаление 0.111534 \n",
"\n",
"4. Построение графиков\n",
" Графики сохранены в: C:\\Users\\weron\\performance_graphs.png\n",
"ЭКСПЕРИМЕНТ ЗАВЕРШЕН УСПЕШНО!\n",
"\n",
" СОЗДАННЫЕ ФАЙЛЫ:\n",
" Данные: C:\\Users\\weron\\experiment_results.csv\n",
" Графики: C:\\Users\\weron\\performance_graphs.png\n"
]
}
],
"source": [
"import time\n",
"import random\n",
"import csv\n",
"import os\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import sys\n",
"sys.setrecursionlimit(20000) \n",
"#Linked List Phone Book:\n",
"\n",
"def ll_insert(head, name, phone):\n",
" new_node = {'name': name, 'phone' : phone, 'next': None}\n",
" if head is None:\n",
" return new_node\n",
" if head['name'] == name:\n",
" head['phone'] = phone\n",
" return head\n",
" current = head \n",
" while current['next'] is not None:\n",
" if current['next']['name'] == name:\n",
" current['next']['phone'] = phone\n",
" return head\n",
" current = current['next']\n",
" current['next'] = new_node\n",
" return head \n",
"def ll_find(head, name):\n",
" current = head\n",
" while current != None:\n",
" if current['name']==name:\n",
" return current['phone']\n",
" current = current['next']\n",
" return None\n",
"def ll_delete(head, name):\n",
" if head is None:\n",
" return None\n",
" if head['name'] == name:\n",
" return head['next']\n",
" current = head \n",
" while current['next'] is not None:\n",
" if current['next']['name'] == name:\n",
" current['next']==current['next']['next']\n",
" return head\n",
" current=current['next']\n",
" return head\n",
"def ll_list_all(head): \n",
" records= []\n",
" current = head \n",
" while current is not None:\n",
" records.append({'name': current['name'], 'phone': current['phone']})\n",
" current = current['next']\n",
" records.sort(key=lambda x: x['name'])\n",
" return records \n",
"def ll_print_all(head):\n",
" records = ll_list_all(head)\n",
" for record in records:\n",
" print(f\"{record['name']}: {record['phone']}\")\n",
"\n",
"#Hash Function:\n",
"\n",
"def hash_function(name, table_size):\n",
" return sum(ord(c) for c in name) % table_size\n",
"\n",
"\n",
"def ht_create(size=1000):\n",
" return [None] * size\n",
"\n",
"\n",
"def ht_insert(buckets, name, phone):\n",
" size = len(buckets)\n",
" index = hash_function(name, size)\n",
" buckets[index] = ll_insert(buckets[index], name, phone)\n",
"\n",
"\n",
"def ht_find(buckets, name):\n",
" size = len(buckets)\n",
" index = hash_function(name, size)\n",
" return ll_find(buckets[index], name)\n",
"\n",
"\n",
"def ht_delete(buckets, name):\n",
" size = len(buckets)\n",
" index = hash_function(name, size)\n",
" buckets[index] = ll_delete(buckets[index], name)\n",
"\n",
"\n",
"def ht_list_all(buckets):\n",
" records = []\n",
" for bucket in buckets:\n",
" current = bucket\n",
" while current is not None:\n",
" records.append((current['name'], current['phone']))\n",
" current = current['next']\n",
" records.sort(key=lambda x: x[0])\n",
" return records\n",
"\n",
"#Tree function:\n",
"\n",
"def bst_insert(root, name, phone):\n",
" \n",
" if root is None:\n",
" return {'name': name, 'phone': phone, 'left': None, 'right': None}\n",
" \n",
" if name < root['name']:\n",
" root['left'] = bst_insert(root['left'], name, phone)\n",
" elif name > root['name']:\n",
" root['right'] = bst_insert(root['right'], name, phone)\n",
" else:\n",
" root['phone'] = phone\n",
" \n",
" return root\n",
"\n",
"\n",
"def bst_find(root, name):\n",
" \n",
" current = root\n",
" while current is not None:\n",
" if name == current['name']:\n",
" return current['phone']\n",
" elif name < current['name']:\n",
" current = current['left']\n",
" else:\n",
" current = current['right']\n",
" return None\n",
"\n",
"\n",
"def bst_find_min(node):\n",
" \n",
" current = node\n",
" while current['left'] is not None:\n",
" current = current['left']\n",
" return current\n",
"\n",
"\n",
"def bst_delete(root, name):\n",
" \n",
" if root is None:\n",
" return None\n",
" \n",
" if name < root['name']:\n",
" root['left'] = bst_delete(root['left'], name)\n",
" elif name > root['name']:\n",
" root['right'] = bst_delete(root['right'], name)\n",
" else:\n",
" if root['left'] is None:\n",
" return root['right']\n",
" elif root['right'] is None:\n",
" return root['left']\n",
" \n",
" min_node = bst_find_min(root['right'])\n",
" root['name'] = min_node['name']\n",
" root['phone'] = min_node['phone']\n",
" root['right'] = bst_delete(root['right'], min_node['name'])\n",
" \n",
" return root\n",
"\n",
"\n",
"def bst_list_all(root):\n",
" \n",
" records = []\n",
" \n",
" def inorder_traversal(node):\n",
" if node is not None:\n",
" inorder_traversal(node['left'])\n",
" records.append((node['name'], node['phone']))\n",
" inorder_traversal(node['right'])\n",
" \n",
" inorder_traversal(root)\n",
" return records\n",
"\n",
"#Experemental part \n",
"#1. Test data generation \n",
"\n",
"def generate_records(count=10000):\n",
" \n",
" records = []\n",
" for i in range(count):\n",
" name = f\"User_{i:05d}\"\n",
" phone = f\"+7-{random.randint(100,999)}-{random.randint(100,999)}-{random.randint(1000,9999)}\"\n",
" records.append((name, phone))\n",
" \n",
" shuffled = records.copy()\n",
" random.shuffle(shuffled)\n",
" sorted_records = sorted(records, key=lambda x: x[0])\n",
" \n",
" return shuffled, sorted_records\n",
"\n",
"#2. Timing\n",
"\n",
"def measure_insertion(structure_name, records):\n",
" \n",
" times = []\n",
" filled_structure = None\n",
" \n",
" for run in range(5):\n",
" if structure_name == \"linked_list\":\n",
" structure = None\n",
" elif structure_name == \"hash_table\":\n",
" structure = ht_create(1000)\n",
" elif structure_name == \"bst\":\n",
" structure = None\n",
" \n",
" start = time.perf_counter()\n",
" \n",
" for name, phone in records:\n",
" if structure_name == \"linked_list\":\n",
" structure = ll_insert(structure, name, phone)\n",
" elif structure_name == \"hash_table\":\n",
" ht_insert(structure, name, phone)\n",
" elif structure_name == \"bst\":\n",
" structure = bst_insert(structure, name, phone)\n",
" \n",
" end = time.perf_counter()\n",
" times.append(end - start)\n",
" \n",
" if run == 4:\n",
" filled_structure = structure\n",
" \n",
" return times, filled_structure\n",
"\n",
"\n",
"def measure_search(structure_name, structure, search_names):\n",
" \n",
" times = []\n",
" \n",
" for run in range(5):\n",
" start = time.perf_counter()\n",
" \n",
" for name in search_names:\n",
" if structure_name == \"linked_list\":\n",
" ll_find(structure, name)\n",
" elif structure_name == \"hash_table\":\n",
" ht_find(structure, name)\n",
" elif structure_name == \"bst\":\n",
" bst_find(structure, name)\n",
" \n",
" end = time.perf_counter()\n",
" times.append(end - start)\n",
" \n",
" return times\n",
"\n",
"\n",
"def measure_deletion(structure_name, original_structure, delete_names):\n",
" \n",
" times = []\n",
" \n",
" for run in range(5):\n",
" if structure_name == \"linked_list\":\n",
" all_records = ll_list_all(original_structure)\n",
" test_structure = None\n",
" for name, phone in all_records:\n",
" test_structure = ll_insert(test_structure, name, phone)\n",
" \n",
" elif structure_name == \"hash_table\":\n",
" all_records = ht_list_all(original_structure)\n",
" test_structure = ht_create(1000)\n",
" for name, phone in all_records:\n",
" ht_insert(test_structure, name, phone)\n",
" \n",
" elif structure_name == \"bst\":\n",
" all_records = bst_list_all(original_structure)\n",
" test_structure = None\n",
" for name, phone in all_records:\n",
" test_structure = bst_insert(test_structure, name, phone)\n",
" \n",
" start = time.perf_counter()\n",
" \n",
" for name in delete_names:\n",
" if structure_name == \"linked_list\":\n",
" test_structure = ll_delete(test_structure, name)\n",
" elif structure_name == \"hash_table\":\n",
" ht_delete(test_structure, name)\n",
" elif structure_name == \"bst\":\n",
" test_structure = bst_delete(test_structure, name)\n",
" \n",
" end = time.perf_counter()\n",
" times.append(end - start)\n",
" \n",
" return times\n",
"#3. Launch and save results\n",
"\n",
"def run_experiment():\n",
" \n",
" current_dir = os.getcwd()\n",
" docs_dir = current_dir\n",
" csv_file = os.path.join(docs_dir, \"experiment_results.csv\")\n",
" \n",
" print(\"ЭКСПЕРИМЕНТАЛЬНОЕ СРАВНЕНИЕ СТРУКТУР ДАННЫХ\")\n",
" print(\"Телефонный справочник - 10000 записей\")\n",
" print(f\"\\n Результаты будут сохранены в: {csv_file}\")\n",
" \n",
" shuffled_records, sorted_records = generate_records(10000)\n",
" print(f\" Сгенерировано 10000 записей\")\n",
" \n",
" existing_names = [shuffled_records[i][0] for i in random.sample(range(10000), 100)]\n",
" nonexisting_names = [f\"NotExist_{i}\" for i in range(10)]\n",
" search_names = existing_names + nonexisting_names\n",
" delete_names = [shuffled_records[i][0] for i in random.sample(range(10000), 50)]\n",
" \n",
" results = [[\"Структура\", \"Режим\", \"Операция\", \n",
" \"Замер1(с)\", \"Замер2(с)\", \"Замер3(с)\", \"Замер4(с)\", \"Замер5(с)\", \n",
" \"Среднее(с)\"]]\n",
" \n",
" for mode_name, records in [(\"случайный\", shuffled_records), \n",
" (\"отсортированный\", sorted_records)]:\n",
" \n",
" print(f\"\\n2. Тестирование режима: {mode_name}\")\n",
" \n",
" for struct_name in [\"linked_list\", \"hash_table\", \"bst\"]:\n",
" print(f\"\\n {struct_name.upper()}:\")\n",
" \n",
" print(\" Вставка 10000 записей\")\n",
" insert_times, filled_struct = measure_insertion(struct_name, records)\n",
" avg_insert = sum(insert_times) / 5\n",
" print(f\" Время: {avg_insert:.4f} сек (среднее)\")\n",
" \n",
" print(\" Поиск 110 записей\")\n",
" search_times = measure_search(struct_name, filled_struct, search_names)\n",
" avg_search = sum(search_times) / 5\n",
" print(f\" Время: {avg_search:.4f} сек (среднее)\")\n",
" \n",
" print(\" Удаление 50 записей\")\n",
" delete_times = measure_deletion(struct_name, filled_struct, delete_names)\n",
" avg_delete = sum(delete_times) / 5\n",
" print(f\" Время: {avg_delete:.4f} сек (среднее)\")\n",
" \n",
" results.append([struct_name, mode_name, \"вставка\"] + insert_times + [avg_insert])\n",
" results.append([struct_name, mode_name, \"поиск\"] + search_times + [avg_search])\n",
" results.append([struct_name, mode_name, \"удаление\"] + delete_times + [avg_delete])\n",
" \n",
" print(\"\\n3. Сохранение результатов\")\n",
" with open(csv_file, \"w\", newline=\"\", encoding=\"utf-8\") as f:\n",
" writer = csv.writer(f)\n",
" writer.writerows(results)\n",
" print(f\" Результаты сохранены в: {csv_file}\")\n",
" \n",
" print(\"СВОДНАЯ ТАБЛИЦА РЕЗУЛЬТАТОВ\")\n",
" print(f\"{'Структура':<15} {'Режим':<12} {'Операция':<10} {'Среднее время (сек)':<20}\")\n",
" \n",
" for row in results[1:]:\n",
" struct, mode, op, t1, t2, t3, t4, t5, avg = row\n",
" print(f\"{struct:<15} {mode:<12} {op:<10} {avg:<20.6f}\")\n",
" \n",
" return results, docs_dir\n",
"\n",
"#4. Graphics\n",
"\n",
"def create_graphs(results, docs_dir):\n",
" \n",
" print(\"\\n4. Построение графиков\")\n",
" \n",
" data = {}\n",
" for row in results[1:]:\n",
" struct = row[0]\n",
" mode = row[1]\n",
" op = row[2]\n",
" avg = row[8]\n",
" \n",
" if struct not in data:\n",
" data[struct] = {}\n",
" if mode not in data[struct]:\n",
" data[struct][mode] = {}\n",
" data[struct][mode][op] = avg\n",
" \n",
" \n",
" struct_labels = {\n",
" 'linked_list': 'LinkedList',\n",
" 'hash_table': 'HashTable',\n",
" 'bst': 'BST'\n",
" }\n",
" \n",
" \n",
" colors = {\n",
" 'linked_list': '#8b00ff', \n",
" 'hash_table': '#81d8d0', \n",
" 'bst': '#000000' \n",
" }\n",
" \n",
" \n",
" fig, axes = plt.subplots(1, 3, figsize=(15, 6))\n",
" fig.suptitle('Сравнение производительности структур данных', fontsize=16, fontweight='bold')\n",
" \n",
" operations = ['вставка', 'поиск', 'удаление']\n",
" operation_titles = ['Вставка\\n(10000 записей)', 'Поиск\\n(110 запросов)', 'Удаление\\n(50 записей)']\n",
" modes = ['случайный', 'отсортированный']\n",
" mode_labels = ['Случайный', 'Отсортированный']\n",
" \n",
" for idx, (op, op_title) in enumerate(zip(operations, operation_titles)):\n",
" ax = axes[idx]\n",
" \n",
" # Позиции для групп столбцов\n",
" x = np.arange(len(modes)) # [0, 1]\n",
" width = 0.3 # ширина одного столбца\n",
" multiplier = 0\n",
" \n",
" for struct in ['linked_list', 'hash_table', 'bst']:\n",
" values = [data[struct][mode][op] for mode in modes]\n",
" offset = width * multiplier\n",
" bars = ax.bar(x + offset, values, width, \n",
" label=struct_labels[struct], \n",
" color=colors[struct],\n",
" edgecolor='black', linewidth=0.5)\n",
" \n",
" \n",
" for bar, val in zip(bars, values):\n",
" if val < 0.01:\n",
" ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + val*0.05, \n",
" f'{val:.5f}', ha='center', va='bottom', fontsize=8, rotation=0)\n",
" else:\n",
" ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + val*0.02, \n",
" f'{val:.4f}', ha='center', va='bottom', fontsize=8, rotation=0)\n",
" \n",
" multiplier += 1\n",
" \n",
" \n",
" ax.set_title(op_title, fontsize=12, fontweight='bold')\n",
" ax.set_ylabel('Время (секунды)', fontsize=10)\n",
" ax.set_xlabel('Режим данных', fontsize=10)\n",
" ax.set_xticks(x + width)\n",
" ax.set_xticklabels(mode_labels)\n",
" ax.legend(loc='upper left', fontsize=8)\n",
" ax.grid(True, alpha=0.3, axis='y')\n",
" \n",
" \n",
" all_values = [data[s][m][op] for s in ['linked_list', 'hash_table', 'bst'] for m in modes]\n",
" if max(all_values) / min(all_values) > 100:\n",
" ax.set_yscale('log')\n",
" ax.set_ylabel('Время (секунды) - логарифмическая шкала', fontsize=9)\n",
" \n",
" plt.tight_layout()\n",
" graph_path = os.path.join(docs_dir, \"performance_graphs.png\")\n",
" plt.savefig(graph_path, dpi=150, bbox_inches='tight')\n",
" plt.close()\n",
" print(f\" Графики сохранены в: {graph_path}\")\n",
" \n",
" return graph_path\n",
"\n",
"#5. Main program\n",
"\n",
"if __name__ == \"__main__\":\n",
" \n",
" results, docs_dir = run_experiment()\n",
" \n",
" \n",
" try:\n",
" graph_file = create_graphs(results, docs_dir)\n",
" \n",
" print(\"ЭКСПЕРИМЕНТ ЗАВЕРШЕН УСПЕШНО!\")\n",
" print(\"\\n СОЗДАННЫЕ ФАЙЛЫ:\")\n",
" print(f\" Данные: {os.path.join(docs_dir, 'experiment_results.csv')}\")\n",
" print(f\" Графики: {graph_file}\")\n",
" \n",
" except Exception as e:\n",
" print(f\"\\n Ошибка при построении графиков: {e}\")\n",
" print(\" Убедитесь, что установлен matplotlib: pip install matplotlib\")\n",
" print(\"ЭКСПЕРИМЕНТ ЗАВЕРШЕН (без графиков)\")\n",
" print(f\"\\n CSV файл сохранен: {os.path.join(docs_dir, 'experiment_results.csv')}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e02735f2-61dc-484b-b74c-1456f7399863",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [conda env:base] *",
"language": "python",
"name": "conda-base-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}