Добавил:
baraevaliza
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабы по АиСД 2023 / Baraeva_Elizaveta_lb3
.pdf
МИНОБРНАУКИ РОССИИ
САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ
ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
«ЛЭТИ» ИМ. В. И. УЛЬЯНОВА (ЛЕНИНА)
Кафедра МО ЭВМ
ОТЧЕТ
по лабораторной работе №3
по дисциплине «Алгоритмы и структуры данных»
Тема: Реализация и исследование АВЛ-деревьев
Студентка гр. 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
