AVL Tree

Back Home

Category

Category: Trees

Topics

Topics: balanced BST, ordered maps/sets, database indexing, consistent performance

Definition

A self-balancing binary search tree where the heights of the left and right subtrees of every node differ by at most one, guaranteeing O(log n) operations.

Use cases

Attributes

Common operations

Operation Time Description
Search O(log n) Guaranteed balanced height
Insert O(log n) Insert + rebalance
Delete O(log n) Delete + rebalance
Min/Max O(log n) Traverse to leaf

In code

class AVLNode:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
        self.height = 1

class AVLTree:
    def height(self, node):
        return node.height if node else 0

    def balance_factor(self, node):
        return self.height(node.left) - self.height(node.right) if node else 0

    def update_height(self, node):
        node.height = 1 + max(self.height(node.left), self.height(node.right))

    def rotate_right(self, y):
        """Right rotation for Left-Left case"""
        x = y.left
        T2 = x.right
        x.right = y
        y.left = T2
        self.update_height(y)
        self.update_height(x)
        return x

    def rotate_left(self, x):
        """Left rotation for Right-Right case"""
        y = x.right
        T2 = y.left
        y.left = x
        x.right = T2
        self.update_height(x)
        self.update_height(y)
        return y

    def insert(self, root, val):
        # Standard BST insert
        if not root:
            return AVLNode(val)
        if val < root.val:
            root.left = self.insert(root.left, val)
        else:
            root.right = self.insert(root.right, val)

        # Update height
        self.update_height(root)

        # Get balance factor
        balance = self.balance_factor(root)

        # Left-Left case
        if balance > 1 and val < root.left.val:
            return self.rotate_right(root)

        # Right-Right case
        if balance < -1 and val > root.right.val:
            return self.rotate_left(root)

        # Left-Right case
        if balance > 1 and val > root.left.val:
            root.left = self.rotate_left(root.left)
            return self.rotate_right(root)

        # Right-Left case
        if balance < -1 and val < root.right.val:
            root.right = self.rotate_right(root.right)
            return self.rotate_left(root)

        return root

    def search(self, root, val):
        if not root or root.val == val:
            return root
        if val < root.val:
            return self.search(root.left, val)
        return self.search(root.right, val)

Time complexity

Space complexity

O(n) for n nodes. Each node stores additional height information (one integer). Recursive operations use O(log n) stack space.

Trade-offs

Pros:

Cons:

Variants

When to use vs avoid