-
Notifications
You must be signed in to change notification settings - Fork 0
Контрольная 2. Разгуляева Ада #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,157 @@ | ||
| class BinomialNode: | ||
| """Узел биномиального дерева""" | ||
| def __init__(self, key, value=None): | ||
| self.key = key # приоритет (меньше = выше приоритет) | ||
| self.value = value # данные, хранимые в узле | ||
| self.degree = 0 # степень узла(количество детей) | ||
| self.parent = None # родительский узел | ||
| self.child = None # указатель на крайнего левого ребенка | ||
| self.sibling = None # указатель на правого брата | ||
|
|
||
| class BinomialHeap: | ||
| """Биномиальная куча (очередь с приоритетами)""" | ||
| def __init__(self): | ||
| self.head = None # голова списка корней | ||
|
|
||
| def is_empty(self): | ||
| """Проверка на пустоту""" | ||
| return self.head is None | ||
|
|
||
|
|
||
| def insert(self, key, value=None): | ||
| """Вставка элемента в кучу""" | ||
| # создаем новую кучу из одного элемента | ||
| node = BinomialNode(key, value) | ||
| new_heap = BinomialHeap() | ||
| new_heap.head = node | ||
|
|
||
| # сливаем с текущей кучей | ||
| self._union(new_heap) | ||
|
|
||
| def get_minimum(self): | ||
| """Поиск минимального элемента""" | ||
| if self.head is None: | ||
| return None | ||
|
|
||
| min_node = self.head | ||
| current = self.head.sibling | ||
|
|
||
| while current: | ||
| if current.key < min_node.key: | ||
| min_node = current | ||
| current = current.sibling | ||
|
|
||
| return min_node | ||
|
|
||
| def _union(self, other_heap): | ||
| """Слияние двух биномиальных куч""" | ||
| merged_head = self._merge_root_lists(self.head, other_heap.head) | ||
|
|
||
| if merged_head is None: | ||
| self.head = None | ||
| return | ||
|
|
||
| prev = None | ||
| x = merged_head | ||
| next_node = x.sibling | ||
|
|
||
| while next_node: | ||
| # степени разные или три дерева подряд одинаковой степени | ||
| if x.degree != next_node.degree or (next_node.sibling == x.degree and next_node.sibling.degree == x.degree): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| prev = x | ||
| x = next_node | ||
| else: | ||
| if x.key <= next_node.key: | ||
| x.sibling = next_node.sibling | ||
| self._link_trees(next_node, x) | ||
| else: | ||
| if prev is None: | ||
| merged_head = next_node | ||
| else: | ||
| prev.sibling = next_node | ||
| self._link_trees(x, next_node) | ||
| x = next_node | ||
|
|
||
| next_node = x.sibling | ||
| self.head = merged_head | ||
|
|
||
| def _merge_root_lists(self, head_1, head_2): | ||
| """Слияние двух списков корней в один отсортированный по степени""" | ||
| temp = BinomialNode(0) | ||
| tail = temp | ||
|
|
||
| while head_1 and head_2: | ||
| if head_1.degree <= head_2.degree: | ||
| tail.sibling = head_1 | ||
| head_1 = head_1.sibling | ||
| else: | ||
| tail.sibling = head_2 | ||
| head_2 = head_2.sibling | ||
| tail = tail.sibling | ||
|
|
||
| if head_1: | ||
| tail.sibling = head_1 | ||
| else: | ||
| tail.sibling = head_2 | ||
|
|
||
| def _link_trees(self, child, parent): | ||
| """Связывание двух деревьев одинаковой степени""" | ||
| child.parent = parent | ||
| child.sibling = parent.child | ||
| parent.child = child | ||
| parent.degree += 1 | ||
|
|
||
| def extract_min(self): | ||
| """Извлечение узла с минимальным значением ключа""" | ||
| if self.head is None: | ||
| return None | ||
|
|
||
| min_node = self.head | ||
| min_prev = None | ||
| prev = None | ||
| current = self.head | ||
|
|
||
| while current: | ||
| if current.key < min_node.key: | ||
| min_node = current | ||
| min_prev = prev | ||
| prev = current | ||
| current = current.sibling | ||
|
|
||
| if min_prev is None: | ||
| self.head = min_node.sibling | ||
| else: | ||
| min_prev.sibling = min_node.sibling | ||
|
|
||
| child_head = None | ||
| child = min_node.child | ||
| while child: | ||
| next_child = child.sibling | ||
| child.sibling = child_head | ||
| child.parent = None | ||
| child_head = child | ||
| child = next_child | ||
|
|
||
| child_heap = BinomialHeap() | ||
| child_heap.head = child_head | ||
| self._union(child_heap) | ||
| return min_node | ||
|
|
||
|
|
||
| def decrease(self, node, value): | ||
| """Уменьшает ключ элемента, присваивая новое значение""" | ||
| if value > node.key: | ||
| return | ||
| node.key = value | ||
| parent = node.parent | ||
| while parent and node.key < parent.key: | ||
| node.key, parent.key = parent.key, node.key | ||
| node.value, parent.value = parent.value, node.value | ||
|
|
||
| node = parent | ||
| parent = node.parent | ||
|
|
||
| def delete(self, node): | ||
| """Удаление ключа""" | ||
| decrease(self, node, -10**9) | ||
|
Check failure on line 156 in src/kr_2/kr_2_queue.py
|
||
| extract_min(self) | ||
|
Check failure on line 157 in src/kr_2/kr_2_queue.py
|
||
|
Comment on lines
+156
to
+157
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. def delete(self, node):
self.decrease(node, -float('inf'))
self.extract_min()
Comment on lines
+141
to
+157
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Эти методы ожидают объект |
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ruff ругается |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| """ | ||
| Запуск: pytest kr_2_queue_tests.py -v | ||
| """ | ||
| from kr_2_queue import BinomialHeap | ||
|
|
||
| class TestBasicOperations: | ||
| """Проверка базовых операций вставки, поиска и извлечения минимума""" | ||
| def test_empty_heap(self): | ||
| """Проверка пустой кучи""" | ||
| heap = BinomialHeap() | ||
| assert heap.is_empty() == True | ||
|
Check failure on line 11 in src/kr_2/kr_2_queue_tests.py
|
||
| assert heap.get_minimum() is None | ||
| assert heap.extract_min() is None | ||
|
|
||
| def test_single_insert(self): | ||
| """Вставка одного элемента""" | ||
| heap = BinomialHeap() | ||
| heap.insert(10, "A") | ||
|
|
||
| assert heap.is_empty() == False | ||
|
Check failure on line 20 in src/kr_2/kr_2_queue_tests.py
|
||
| min_node = heap.get_minimum() | ||
| assert min_node.key == 10 | ||
| assert min_node.value == "A" | ||
|
|
||
| def test_multiple_inserts(self): | ||
| """Вставка нескольких элементов""" | ||
| heap = BinomialHeap() | ||
| heap.insert(10, "A") | ||
| heap.insert(5, "B") | ||
| heap.insert(20, "C") | ||
| heap.insert(3, "D") | ||
| heap.insert(7, "E") | ||
|
|
||
| # проверка поиска минимума | ||
| min_node = heap.get_minimum() | ||
| assert min_node.key == 3 | ||
| assert min_node.value == "D" | ||
|
|
||
| # проверка извлечения минимума | ||
| extracted = heap.extract_min() | ||
| assert extracted.key == 3 | ||
| assert extracted.value == "D" | ||
|
|
||
| # проверка нового минимума | ||
| min_node = heap.get_minimum() | ||
| assert min_node.key == 5 | ||
| assert min_node.value == "B" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_merge_root_listsничего не возвращает, а значит дальнейшее выполнение функции неверно