Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы по АиСД 2023 / Baraeva_Elizaveta_lb3

.pdf
Скачиваний:
0
Добавлен:
09.09.2026
Размер:
258 Кб
Скачать
МИНОБРНАУКИ РОССИИ
САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ
ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
«ЛЭТИ» ИМ. В. И. УЛЬЯНОВА (ЛЕНИНА)
Кафедра МО ЭВМ
ОТЧЕТ
по дисциплине «Алгоритмы и структуры данных»
Тема: Реализация и исследование АВЛ-деревьев
Студентка гр. 2383
Бараева Е. Н.
Преподаватель
Гаврилов А. В.
Санкт-Петербург
2023
2
Цель работы.
Реализация и тестирование АВЛ-дерева, исследование функций данной структуры на различных размерах данных, сравнение полученных результатов с теоретической оценкой.
Задание.
В предыдущих лабораторных работах вы уже проводили исследования и
эта не будет исключением. Как и в прошлые разы лабораторную работу
можно разделить на две части:
1) решение задач на платформе moodle
2) исследование по заданной теме
В заданиях в качестве подсказки будет изложена основная структура
данных (класс узла) и будет необходимо реализовать несколько основных
функций: проверка дерева (является ли оно АВЛ деревом), нахождение
разницы между связными узлами, вставка узла.
В качестве исследования нужно самостоятельно:
реализовать функции удаления узлов: любого, максимального и
минимального
сравнить время и количество операций, необходимых для
реализованных операций, с теоретическими оценками (очевидно, что
проводить исследования необходимо на разных объемах данных)
В отчете помимо проведенного исследования необходимо приложить код
всей получившей структуры: класс узла и функции.
Выполнение работы.
Класс Node имеет поля val (значение узла), left (левый дочерний узел) и right (правый дочерний узел). Конструктор класса устанавливает значения
этих полей.
Функция height вычисляет высоту дерева, начиная с заданного узла.
3
Функция check проверяет, является ли дерево сбалансированным. Для
этого она сравнивает разницу между высотами левого и правого поддеревьев
каждого узла и возвращает False, если эта разница больше 1.
Функция diff вычисляет минимальную разницу между значением узла и
значениями его дочерних узлов. Она рекурсивно вызывает себя для левого и
правого поддеревьев и сравнивает полученные значения с текущим
минимальной разницей.
Функция balance вычисляет коэффициент сбалансированности узла. Коэффициент сбалансированности – это разница между высотами левого и правого поддеревьев узла.
Функция min_val_node находит пустой наименьший узел в дереве. Она
итеративно спускается по левым потомкам узла, пока не достигнет
наименьшего узла.
Функции right_rotate и left_rotate выполняют правый и левый повороты
соответственно. Эти операции используются для балансировки дерева при
вставке или удалении узлов.
Функция insert вставляет новый узел со значением val в заданное дерево.
Если заданное дерево пусто, она создает новый узел с заданным значением.
Она также обновляет высоты узлов и выполняет повороты, если необходимо,
чтобы сохранить сбалансированность дерева.
Функция delete удаляет узел с заданным значением из заданного дерева.
Если узел, который нужно удалить, имеет двух потомков, его значение
заменяется на значение наименьшего узла в правом поддереве, а затем этот
наименьший узел удаляется. Если у узла нет одного или обоих потомков, он
просто удаляется. После удаления узла обновляются высоты узлов и
выполняются необходимые повороты для сохранения сбалансированности
дерева.
Функция find_node находит узел с заданным значением в дереве.
4
Функции find_min и find_max находят узлы с наименьшим и наибольшим
значениями соответственно в дереве. Они итеративно спускаются по левым
(в случае функции find_min) или правым (в случае функции find_max) потомкам до достижения наименьшего или наибольшего значения.
Функции delete_min_node и delete_max_node сначала находят минимальный узел node случае функции delete_min_node) или максимальный (в случае функции delete_max_node). Затем они сохраняют значение данного узла в переменную value и вызывает функцию delete для удаления узла.
Разработанный программный код см. в приложении А.
Тестирование.
Результаты тестирования представлены в табл. 1. Таблица 1 – Результаты тестирования
п/п
Входные данные
Выходные данные
Комментарии
1.
root = main.Node(4) root = main.insert(5, root) root = main.insert(7, root) root = main.insert(2, root) root = main.insert(1, root) root = main.insert(3, root) a = main.delete_max_node(root) print(a.val)
7
Проверка
вставки. Верно.
2.
root = Node(5) print(diff(root))
inf
Проверка
функции diff. Верно.
3.
root = main.Node(23) root.left = main.Node(15) root.right = main.Node(56) root.left.left = main.Node(43) root.left.right = main.Node(24) assert main.check(root)
ok
Проверка
функции check. Верно.
Вывод.
Были реализованы основные операции АВЛ-дерева, такие как вставка, удаление и балансировка. Исходя из проведённого исследования можно
5
заметить логарифмическую зависимость времени операции от количества элементов в структуре данных.
6
ПРИЛОЖЕНИЕ А
ИСХОДНЫЙ КОД ПРОГРАММЫ
Название файла: main.py
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
def height(node):
if node is None:
return 0
return 1 + max(height(node.left), height(node.right))
def check(node):
if node is None:
return True
if abs(height(node.left) - height(node.right)) > 1:
return False
return check(node.left) and check(node.right)
def diff(root):
min_diff = float('inf')
if root is None:
return min_diff
if root.left is not None:
min_diff = min(min_diff, abs(root.val - root.left.val))
if root.right is not None:
min_diff = min(min_diff, abs(root.val - root.right.val))
min_diff = min(min_diff, diff(root.left))
min_diff = min(min_diff, diff(root.right))
return min_diff
def balance(node):
if node is None:
return 0
else:
return height(node.left) - height(node.right)
def min_val_node(node):
if node is None or node.left is None:
return node
else:
return min_val_node(node.left)
def right_rotate(node):
a = node.left
b = a.right
a.right = node
7
node.left = b
node.height = 1 + max(height(node.left), height(node.right))
a.height = 1 + max(height(a.left), height(a.right))
return a
def left_rotate(node):
a = node.right
b = a.left
a.left = node
node.right = b
node.height = 1 + max(height(node.left), height(node.right))
a.height = 1 + max(height(a.left), height(a.right))
return a
def insert(val, root):
if root is None:
return Node(val)
elif val <= root.val:
root.left = insert(val, root.left)
elif val > root.val:
root.right = insert(val, root.right)
root.height = 1 + max(height(root.left), height(root.right))
balance_coefficient = balance(root)
if balance_coefficient > 1 and root.left.val > val:
return right_rotate(root)
if balance_coefficient < -1 and val > root.right.val:
return left_rotate(root)
if balance_coefficient > 1 and val > root.left.val:
root.left = left_rotate(root.left)
return right_rotate(root)
if balance_coefficient < -1 and val < root.right.val:
root.right = right_rotate(root.right)
return left_rotate(root)
return root
def delete(val, node):
if node is None:
return node
elif val < node.val:
node.left = delete(val, node.left)
elif val > node.val:
node.right = delete(val, node.right)
else:
if node.left is None and node.right is None:
temp = node
node = None
return temp
if node.left is None:
return node.right
elif node.right is None:
return node.left
rgt = min_val_node(node.right)
node.value = rgt.value
node.right = delete(rgt.value, node.right)
if node is None:
8
return node
node.height = 1 + max(height(node.left), height(node.right))
balance_coefficient = balance(node)
if balance_coefficient > 1 and balance(node.left) >= 0:
return right_rotate(node)
if balance_coefficient < -1 and balance(node.right) <= 0:
return left_rotate(node)
if balance_coefficient > 1 and balance(node.left) < 0:
node.left = left_rotate(node.left)
return right_rotate(node)
if balance_coefficient < -1 and balance(node.right) > 0:
node.right = right_rotate(node.right)
return left_rotate(node)
return node
def find_node(val, root):
if root is None:
return None
elif val < root.val:
return find_node(val, root.left)
elif val > root.key:
return find_node(val, root.right)
else:
return root
def find_min(root):
if root.left is not None:
return find_min(root.left)
else:
return root
def find_max(root):
if root.right is not None:
return find_max(root.right)
else:
return root
def delete_min_node(root):
node = find_min(root)
value = node.val
return delete(value, node)
def delete_max_node(root):
node = find_max(root)
value = node.val
return delete(value, node)
Название файла: test.py
import main
def test_is_balance_check():
9
root = main.Node(23) root.left = main.Node(15) root.right = main.Node(56) root.left.left = main.Node(43) root.left.right = main.Node(24) assert main.check(root)
def test_one_diff(): root = main.Node(5) assert main.diff(root) == float('inf')
def test_none_diff(): root = None assert main.diff(root) == float('inf')
def test_five_diff(): root = main.Node(2) root.left = main.Node(1000) root.right = main.Node(50) root.left.left = main.Node(20) root.left.right = main.Node(90) assert main.diff(root) == 48
def test_one_insert(): root = None root = main.insert(0, root) assert root.val == 0
def test_two_insert(): root = main.Node(9) root = main.insert(3, root) assert root.val == 9 assert root.left.val == 3
def test_insert_balancing(): root = main.Node(3) root = main.insert(40, root) root = main.insert(29, root) root = main.insert(123, root) root = main.insert(10, root) root = main.insert(65, root) root = main.insert(17, root) assert root.val == 29 assert root.left.val == 10 assert root.right.val == 65 assert root.right.right.val == 123 assert root.right.left.val == 40 assert root.left.right.val == 17 assert root.left.left.val == 3
def test_delete_max():
10
root = main.Node(4) root = main.insert(5, root) root = main.insert(7, root) root = main.insert(2, root) root = main.insert(1, root) root = main.insert(3, root) a = main.delete_max_node(root) assert a.val == 7 assert root.left.val == 2 assert root.right.val == 5 assert root.left.left.val == 1 assert root.left.right.val == 3
def test_delete_min(): root = main.Node(68) root = main.insert(65, root) root = main.insert(87, root) root = main.insert(31, root) root = main.insert(18, root) a = main.delete_min_node(root) assert a.val == 18 assert root.val == 68 assert root.left.val == 31 assert root.right.val == 87
assert root.left.right.val == 65
Соседние файлы в папке Лабы по АиСД 2023