Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лаба по деревьям - 3 сем АИСД.docx
Скачиваний:
0
Добавлен:
08.07.2025
Размер:
1.56 Mб
Скачать

Графики для авл-дерева

from AVL import AVL_func

import matplotlib.pyplot as plt

import numpy as np

l = 1000

k = []

for i in range(1,l+1):

k.append(i)

m = []

for o in range(1,l+1):

m.append(k[:o])

he = []

ma = []

for j in range(len(m)):

avl = AVL_func()

root = None

for key in m[j]:

root = avl.insert(root, key)

ma.append(len(m[j]))

#print(avl.level_order_traversal(root))

hei=avl.height_of_tree(root)

#print("Высота дерева:", hei)

#k.append(j_x)

he.append(hei)

print(ma[0],he[0])

for i in range(1,len(ma)):

if he[i-1] != he[i]:

print(ma[i],he[i])

x1 = ma

y1 = he

n = np.linspace(1, 1000, 400) # от 1 до 100, 400 точек

y = 1.44* np.log2(n+1) - 1.33

plt.plot(n, y, label='2*log(n) - 1.44', color='black', )

plt.plot(ma, he, color = 'blue')

plt.title('Зависимость высоты AVL-дерева от количества ключей')

plt.xlabel('Количество ключей')

plt.ylabel('Высота дерева h')

plt.grid()

plt.show()

x = np.array(x1)

y = np.array(y1)

log_x = np.log(x)

coefficients = np.polyfit(log_x, y, 1)

print('коэффы:', coefficients)

regression_line = np.polyval(coefficients, log_x)

#plt.scatter(x, y, label="Данные", color="blue")

plt.plot(x1, y1, color = 'blue')

plt.plot(x, regression_line, label="Регрессионная кривая", color="red")

plt.title("Зависимость высоты AVL-дерева от количества ключей")

plt.xlabel('Количество ключей')

plt.ylabel('Высота дерева')

plt.grid()

plt.show()

АВЛ-дерево

class TreeNode:

def __init__(self, key):

self.left = None

self.right = None

self.val = key

self.height = 0 # Для AVL-дерева

class AVL_func:

def search(self, root, key):

if root is None or root.val == key:

return root

if key < root.val:

return self.search(root.left, key)

return self.search(root.right, key)

def insert(self, root, key):

if not root:

return TreeNode(key)

elif key < root.val:

root.left = self.insert(root.left, key)

else:

root.right = self.insert(root.right, key)

# 2. Обновить высоту узла предка

root.height = 1 + max(self.height_of_tree(root.left), self.height_of_tree(root.right))

# 3. Получить баланс

balance = self.get_balance(root)

# Если дерево не сбалансировано, выполняем повороты

# Левый левый случай

if balance > 1 and key < root.left.val:

return self.rotate_right(root)

# Правый правый случай

if balance < -1 and key > root.right.val:

return self.rotate_left(root)

# Левый правый случай

if balance > 1 and key > root.left.val:

root.left = self.rotate_left(root.left)

return self.rotate_right(root)

# Правый левый случай

if balance < -1 and key < root.right.val:

root.right = self.rotate_right(root.right)

return self.rotate_left(root)

return root

def delete_node(self, root, key):

# 1. Выполняем стандартное удаление узла

if not root:

return root

elif key < root.val:

root.left = self.delete_node(root.left, key)

elif key > root.val:

root.right = self.delete_node(root.right, key)

else:

# Узел с одним ребенком или без детей

if root.left is None:

return root.right

elif root.right is None:

return root.left

# Узел с двумя детьми: получить порядокный преемник (наименьшее в правом поддереве)

temp = self.get_min_value_node(root.right)

root.val = temp.val

root.right = self.delete_node(root.right, temp.val)

# 2. Обновить высоту узла предка

root.height = 1 + max(self.height_of_tree(root.left), self.height_of_tree(root.right))

# 3. Получить баланс

balance = self.get_balance(root)

# Если дерево не сбалансировано, выполним необходимые повороты

# Левый левый случай

if balance > 1 and self.get_balance(root.left) >= 0:

return self.rotate_right(root)

# Левый правый случай

if balance > 1 and self.get_balance(root.left) < 0:

root.left = self.rotate_left(root.left)

return self.rotate_right(root)

# Правый правый случай

if balance < -1 and self.get_balance(root.right) <= 0:

return self.rotate_left(root)

# Правый левый случай

if balance < -1 and self.get_balance(root.right) > 0:

root.right = self.rotate_right(root.right)

return self.rotate_left(root)

return root

def get_min_value_node(self, node):

current = node

while current.left is not None:

current = current.left

return current

def height_of_tree(self, node):

if not node:

return 0

return node.height

def get_balance(self, node):

if not node:

return 0

bal = self.height_of_tree(node.left) - self.height_of_tree(node.right)

#print(f"balanced:{bal}")

# return self.height_of_tree(node.left) - self.height_of_tree(node.right)

return bal

def rotate_left(self, z):

y = z.right

T2 = y.left

# Выполняем поворот

y.left = z

z.right = T2

# Обновляем высоты

z.height = 1 + max(self.height_of_tree(z.left), self.height_of_tree(z.right))

y.height = 1 + max(self.height_of_tree(y.left), self.height_of_tree(y.right))

# Возвращаем новый корень

#print("rotate_left")

return y

def rotate_right(self, z):

y = z.left

T3 = y.right

# Выполняем поворот

y.right = z

z.left = T3

# Обновляем высоты

z.height = 1 + max(self.height_of_tree(z.left), self.height_of_tree(z.right))

y.height = 1 + max(self.height_of_tree(y.left), self.height_of_tree(y.right))

#print("rotate_right")

# Возвращаем новый корень

return y

def preorder(self, root):

if root is not None:

print(root.val, end=' ')

self.preorder(root.left)

self.preorder(root.right)

def inorder(self, root):

if root is not None:

self.inorder(root.left)

print(root.val, end=' ')

self.inorder(root.right)

def postorder(self, root):

if root is not None:

self.postorder(root.left)

self.postorder(root.right)

print(root.val, end=' ')

def level_order_traversal(self, root):

if root is None:

return []

result = []

queue = [root] # Используем список в качестве очереди

while queue:

current = queue.pop(0) # Удаляем первый элемент из списка

result.append(current.val)

# Добавляем дочерние элементы в конец списка

if current.left:

queue.append(current.left)

if current.right:

queue.append(current.right)

return result