0% found this document useful (0 votes)
15 views9 pages

AVL Tree With Comments

The document defines an AVL tree implementation in Python, including methods for inserting and deleting nodes while maintaining balance. It also includes functionality to read from an input file, perform operations on the AVL tree, and write the sorted output to a file. The main function orchestrates these operations, demonstrating the AVL tree's capabilities with sample data.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views9 pages

AVL Tree With Comments

The document defines an AVL tree implementation in Python, including methods for inserting and deleting nodes while maintaining balance. It also includes functionality to read from an input file, perform operations on the AVL tree, and write the sorted output to a file. The main function orchestrates these operations, demonstrating the AVL tree's capabilities with sample data.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 9

# Define a node in the AVL tree

class AVLNode:

def __init__(self, key):

self.key = key # The key (value) of the node

self.left = None # Left child node

self.right = None # Right child node

self.height = 1 # Height of the node, starts at 1 (leaf node)

# Define the AVL Tree class

class AVLTree:

def __init__(self):

self.root = None # Root node of the AVL tree

# Public method to insert a key into the AVL tree

def insert(self, key):

self.root = self._insert(self.root, key) # Call the recursive insert method

# Recursive method to insert a key into the tree

def _insert(self, node, key):

# Base case: if the node is None, create a new node with the given key

if not node:

return AVLNode(key)

# If the key to insert is less than the current node's key, go to the left subtree

if key < node.key:

node.left = self._insert(node.left, key)

# If the key to insert is greater than the current node's key, go to the right subtree

elif key > node.key:

node.right = self._insert(node.right, key)


# If the key is equal to the current node's key, do nothing (no duplicates)

else:

return node

# Update the height of the current node based on the heights of its children

node.height = 1 + max(self._get_height(node.left), self._get_height(node.right))

# Get the balance factor to check if the node is unbalanced

balance = self._get_balance(node)

# If the node is unbalanced, there are 4 possible cases to handle

# Case 1: Left Left Case (right rotation needed)

if balance > 1 and key < node.left.key:

return self._rotate_right(node)

# Case 2: Left Right Case (left-right rotation needed)

if balance > 1 and key > node.left.key:

node.left = self._rotate_left(node.left)

return self._rotate_right(node)

# Case 3: Right Right Case (left rotation needed)

if balance < -1 and key > node.right.key:

return self._rotate_left(node)

# Case 4: Right Left Case (right-left rotation needed)

if balance < -1 and key < node.right.key:

node.right = self._rotate_right(node.right)

return self._rotate_left(node)
# Return the (potentially new) root of this subtree

return node

# Public method to delete a key from the AVL tree

def delete(self, key):

self.root = self._delete(self.root, key) # Call the recursive delete method

# Recursive method to delete a key from the tree

def _delete(self, node, key):

# Base case: if the node is None, just return it

if not node:

return node

# If the key to delete is less than the current node's key, go to the left subtree

if key < node.key:

node.left = self._delete(node.left, key)

# If the key to delete is greater than the current node's key, go to the right subtree

elif key > node.key:

node.right = self._delete(node.right, key)

# If the key is equal to the current node's key, this is the node to delete

else:

# Case 1: Node has only one child or no child

if not node.left:

return node.right

if not node.right:

return node.left

# Case 2: Node has two children, get the in-order successor (smallest in the right subtree)
temp = self._get_min_value_node(node.right)

node.key = temp.key # Copy the in-order successor's key to this node

node.right = self._delete(node.right, temp.key) # Delete the in-order successor

# If the node is None after deletion, just return it

if not node:

return node

# Update the height of the current node

node.height = 1 + max(self._get_height(node.left), self._get_height(node.right))

# Get the balance factor to check if the node is unbalanced

balance = self._get_balance(node)

# If the node is unbalanced, there are 4 possible cases to handle

# Case 1: Left Left Case (right rotation needed)

if balance > 1 and self._get_balance(node.left) >= 0:

return self._rotate_right(node)

# Case 2: Left Right Case (left-right rotation needed)

if balance > 1 and self._get_balance(node.left) < 0:

node.left = self._rotate_left(node.left)

return self._rotate_right(node)

# Case 3: Right Right Case (left rotation needed)

if balance < -1 and self._get_balance(node.right) <= 0:

return self._rotate_left(node)
# Case 4: Right Left Case (right-left rotation needed)

if balance < -1 and self._get_balance(node.right) > 0:

node.right = self._rotate_right(node.right)

return self._rotate_left(node)

# Return the (potentially new) root of this subtree

return node

# Method to perform a left rotation on a subtree rooted at 'z'

def _rotate_left(self, z):

y = z.right # 'y' becomes the new root of the subtree

T2 = y.left # 'T2' is the left subtree of 'y' that becomes the right subtree of 'z'

# Perform rotation

y.left = z

z.right = T2

# Update heights of the nodes

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

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

# Return the new root of the subtree

return y

# Method to perform a right rotation on a subtree rooted at 'z'

def _rotate_right(self, z):

y = z.left # 'y' becomes the new root of the subtree

T3 = y.right # 'T3' is the right subtree of 'y' that becomes the left subtree of 'z'
# Perform rotation

y.right = z

z.left = T3

# Update heights of the nodes

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

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

# Return the new root of the subtree

return y

# Method to get the height of a node

def _get_height(self, node):

if not node:

return 0 # If the node is None, return height as 0

return node.height # Otherwise, return the height of the node

# Method to get the balance factor of a node

def _get_balance(self, node):

if not node:

return 0 # If the node is None, balance factor is 0

return self._get_height(node.left) - self._get_height(node.right) # Balance factor: height(left


subtree) - height(right subtree)

# Method to find the node with the smallest key in a subtree

def _get_min_value_node(self, node):

if node is None or node.left is None:

return node # The smallest key is in the leftmost node

return self._get_min_value_node(node.left)
# Method to perform in-order traversal of the tree and collect keys in a list

def in_order_traversal(self, node, result):

if node:

self.in_order_traversal(node.left, result) # Traverse the left subtree

result.append(node.key) # Visit the root

self.in_order_traversal(node.right, result) # Traverse the right subtree

# Function to read elements from a file

def read_elements_from_file(filename):

try:

with open(filename, 'r') as file:

content = file.read().strip() # Read and strip whitespace from the file

print(f"File content read: {content}")

elements = content.split() # Split the content into individual elements

# Convert elements to integers, ignoring non-digit elements

return [int(e) for e in elements if e.isdigit()]

except FileNotFoundError:

print(f"File {filename} not found.")

return []

except ValueError as e:

print(f"ValueError encountered: {e}")

return []

# Function to write elements to a file

def write_elements_to_file(filename, elements):

with open(filename, 'w') as file:

file.write(' '.join(map(str, elements))) # Write elements to the file separated by spaces


# Main function to execute the program

def main():

input_filename = 'input.txt'

output_filename = 'output.txt'

# Read elements from the input file

elements = read_elements_from_file(input_filename)

# If no elements were read, print a message and return

if not elements:

print("No elements to insert into the AVL Tree.")

return

# Create an AVL tree and insert the elements

avl_tree = AVLTree()

for element in elements:

avl_tree.insert(element)

# Additional operations (for example)

avl_tree.insert(15)

avl_tree.delete(20)

# Perform in-order traversal to get the sorted elements

result = []

avl_tree.in_order_traversal(avl_tree.root, result)

write_elements_to_file(output_filename, result) # Write the result to the output file

print("Output written to", output_filename)


# Execute main function if the script is run directly

if __name__ == '__main__':

main()

# Read and print the content of the output file

with open('output.txt', 'r') as file:

output = file.read()

print("Output content:", output)

OUTPUT :-

File content read: 10 20 30 40 50 25 15 5

Output written to output.txt

Output content: 5 10 15 25 30 40 50

You might also like