From 67897bd14b000718dacbfcaa9b0039a418aaedbf Mon Sep 17 00:00:00 2001 From: Proninvv Date: Thu, 19 Mar 2026 14:04:50 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D1=8B=20=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80=D1=8B?= =?UTF-8?q?=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ProninVV/aufgabe-1-data-structures/aufg1.py | 275 ++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 ProninVV/aufgabe-1-data-structures/aufg1.py diff --git a/ProninVV/aufgabe-1-data-structures/aufg1.py b/ProninVV/aufgabe-1-data-structures/aufg1.py new file mode 100644 index 0000000..90d121b --- /dev/null +++ b/ProninVV/aufgabe-1-data-structures/aufg1.py @@ -0,0 +1,275 @@ +# LInkedList (Node = List = {'name': 'Имя', 'phone': '123', 'next': None}) имена уникальные (id) + + +def ll_insert(head, name, phone): + + """ проходит до конца (или сразу добавляет в конец) и возвращает новую голову + (если вставка в начало) или изменяет список по ссылке. Удобнее возвращать новую + голову, если вставка может быть в начало """ + + new_node = {'name': name, 'phone': phone, 'next': None} + + # если списка не было + if head is None: + return new_node + + # # вставка в начало O(1) + # new_node = {'name': name, 'phone': phone, 'next': head} + # return new_node + + # вставка в конец O(n) + current = head + while current['next'] is not None: + # проверка существования данного идентификатора (обновляем запись) + if current['name'] == name: + current['phone'] = phone + return head + current = current['next'] + + # проверка на id + if current['name'] == name: + current['phone'] = phone + else: current['next'] = new_node + return head + + +def ll_find(head, name): + + """ ищет узел, возвращает телефон или None """ + + 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: + new_head = head['next'] + head['next'] = None + return new_head + + # Если не первый + current = head + while current['next'] is not None: + if current['next']['name'] == name: + target = current['next'] + current['next'] = target['next'] + target['next'] = None + return head + current = current['next'] + + return head + + + +def ll_list_all(head): + + """ собирает все записи в список и сортирует (сортировка вынесена отдельно) """ + + length = ll_Lenght(head) + new_list = [None]*length + current = head + for i in range(length): + new_list[i] = (current['name'], current['phone']) + current = current['next'] + sorten(new_list) + return new_list + + +# вспомогательные функции-------------------------------- +def ll_Lenght(head): + # длина связного списка + counter = 0 + curr = head + while curr: + counter += 1 + curr = curr['next'] + return counter + + +def sorten(arr): + n = len(arr) + for i in range(n): + for j in range(0, n - i - 1): + if arr[j][0] > arr[j + 1][0]: + arr[j], arr[j + 1] = arr[j + 1], arr[j] +# ----------------------------------------------------------- + +# linklist = None +# linklist = ll_insert(linklist, 'Sjora', '123') +# linklist = ll_insert(linklist, 'Vlad', '0000') +# linklist = ll_insert(linklist, 'Dima', '228') + +# print(linklist) +# print(ll_find(linklist, 'Vlad')) +# print(ll_delete(linklist, 'Dima')) +# print(ll_list_all(linklist)) + +# HashTable (Хранится как список buckets фиксированной длины, каждый элемент — голова связного списка (или None)) + +def hash_table(size): + return [None]*size + + +def hash_func(name, buckets_count): + h = 0 + for char in name: + h += ord(char) + return h % buckets_count + + +def ht_insert(buckets, name, phone): + + """ вычисляет индекс, вызывает ll_insert для соответствующего бакета """ + + if buckets is None: + return + + index = hash_func(name, len(buckets)) + buckets[index] = ll_insert(buckets[index], name, phone) + + + +def ht_find(buckets, name): + """ """ + idx = hash_func(name, len(buckets)) + return ll_find(buckets[idx], name) + + +def ht_delete(buckets, name): + idx = hash_func(name, len(buckets)) + buckets[idx] = ll_delete(buckets[idx], name) + + +def ht_list_all(buckets): + + """ собирает все записи из всех бакетов и сортирует """ + total_count = 0 + for head in buckets: + total_count += ll_Lenght(head) + + full_data = [None]*total_count + + k = 0 + for head in buckets: + curr = head + while curr: + full_data[k] = (curr['name'], curr['phone']) + k += 1 + curr = curr['next'] + + sorten(full_data) + return full_data + +# Hash_table1 = hash_table(3) +# ht_insert(Hash_table1, 'Vlad', '000') +# ht_insert(Hash_table1, 'Dima', '111') +# ht_insert(Hash_table1, 'Sjora', '222') + +# print(ht_list_all(Hash_table1)) + +# Двоичное дерево поиска : Узел — словарь: {'name': 'Имя', 'phone': '123', 'left': None, 'right': None} + +def bst_insert(root, name, phone): + + """ рекурсивно или итеративно вставляет, возвращает новый корень (если корень меняется) """ + + new_node = {'name': name, 'phone': phone, 'left': None, 'right': None} + + # если дерева нет + if root is None: + return new_node + + 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 root['name'] == name: + return root['phone'] + + elif name < root['name']: + return bst_find(root['left'], name) + + elif name > root['name']: + return bst_find(root['right'], name) + + +def bst_delete(root, name): + + """ удаление, возвращает новый корень """ + + if root is None: + return None + + # спускаемся к нужному узлу (аналогично поиску) + elif 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 and root['right'] is None: + # обрываем связь + return None + # если только один наследник + elif root['left'] is None != root['right'] is None: + return root['left'] or root['right'] + # два наследника (поиск минимального поддерева в правой ветке) + + successor = root['right'] + while successor['left'] is not None: + successor = root['left'] + + root['name'] = successor['name'] + root['phone'] = successor['phone'] + # Удаляем дубликат преемника в правом поддереве + root['right'] = bst_delete(root['right'], successor['name']) + return root + + +def bst_list_all(root, result=None): + """ центрированный обход (рекурсивно собирает записи в отсортированном порядке) """ + if result is None: + result = [] + # сначала спускаемся по левой стороне вниз, затем идем вверх и вправо + if root is not None: + bst_list_all(root['left'], result) + result.append((root['name'], root['phone'])) + bst_list_all(root['right'], result) + return result + +# derevo = None +# derevo = bst_insert(derevo, 'Vlad', '000') +# derevo = bst_insert(derevo, 'Dima', '111') +# derevo = bst_insert(derevo, 'Sjora', '222') +# derevo = bst_insert(derevo, 'weid', '0') + +# # print(derevo) +# # derevo = bst_delete(derevo, 'Vlad') +# print(bst_list_all(derevo))