欢迎访问宙启技术站
智能推送

使用Java函数实现AVL树的插入、删除、旋转等操作

发布时间:2023-06-13 17:54:42

AVL树是一种自平衡二叉搜索树,其每个节点的左右子树的高度差不超过1。为了保持AVL树的平衡,需要对树进行旋转操作。本文将使用Java函数实现AVL树的插入、删除、旋转等操作。

1. AVL树的节点定义

首先,需要定义AVL树的节点。节点包含三个属性:值、左子树节点、右子树节点和高度。其中,高度是指当前节点的子树高度。

class AVLNode {
    int val; // 节点的值
    AVLNode left; // 左子树的节点
    AVLNode right; // 右子树的节点
    int height; // 高度

    AVLNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
        this.height = 1;
    }
}

2. AVL树的插入操作

AVL树的插入操作需要先按照二叉搜索树的规则找到插入位置,然后进行平衡调整。平衡调整包括四种情况:LL、RR、LR和RL。

- LL情况:在节点的左子树的左子树上插入节点,需要进行右旋操作。

- RR情况:在节点的右子树的右子树上插入节点,需要进行左旋操作。

- LR情况:在节点的左子树的右子树上插入节点,需要先进行左旋操作,再进行右旋操作。

- RL情况:在节点的右子树的左子树上插入节点,需要先进行右旋操作,再进行左旋操作。

下面是Java函数实现AVL树的插入操作。

public AVLNode insert(AVLNode root, int val) {
    if (root == null) {
        return new AVLNode(val);
    }

    if (val < root.val) {
        root.left = insert(root.left, val);
    } else if (val > root.val) {
        root.right = insert(root.right, val);
    } else {
        // 如果值重复,无需插入
        return root;
    }

    // 更新节点的高度
    root.height = 1 + Math.max(height(root.left), height(root.right));

    // 计算节点的平衡因子
    int balance = getBalance(root);

    // LL情况,右旋
    if (balance > 1 && val < root.left.val) {
        return rightRotate(root);
    }

    // RR情况,左旋
    if (balance < -1 && val > root.right.val) {
        return leftRotate(root);
    }

    // LR情况,先左旋再右旋
    if (balance > 1 && val > root.left.val) {
        root.left = leftRotate(root.left);
        return rightRotate(root);
    }

    // RL情况,先右旋再左旋
    if (balance < -1 && val < root.right.val) {
        root.right = rightRotate(root.right);
        return leftRotate(root);
    }

    return root;
}

// 左旋
private AVLNode leftRotate(AVLNode node) {
    AVLNode right = node.right;
    AVLNode left = right.left;

    right.left = node;
    node.right = left;

    node.height = 1 + Math.max(height(node.left), height(node.right));
    right.height = 1 + Math.max(height(right.left), height(right.right));

    return right;
}

// 右旋
private AVLNode rightRotate(AVLNode node) {
    AVLNode left = node.left;
    AVLNode right = left.right;

    left.right = node;
    node.left = right;

    node.height = 1 + Math.max(height(node.left), height(node.right));
    left.height = 1 + Math.max(height(left.left), height(left.right));

    return left;
}

// 获取节点的高度
private int height(AVLNode node) {
    if (node == null) {
        return 0;
    }
    return node.height;
}

// 获取节点的平衡因子
private int getBalance(AVLNode node) {
    if (node == null) {
        return 0;
    }
    return height(node.left) - height(node.right);
}

3. AVL树的删除操作

AVL树的删除操作也需要先按照二叉搜索树的规则找到删除节点位置,然后进行平衡调整。平衡调整跟插入操作的四种情况对应。

- LL情况:在节点的左子树的左子树上删除节点,需要进行右旋操作。

- RR情况:在节点的右子树的右子树上删除节点,需要进行左旋操作。

- LR情况:在节点的左子树的右子树上删除节点,需要先进行左旋操作,再进行右旋操作。

- RL情况:在节点的右子树的左子树上删除节点,需要先进行右旋操作,再进行左旋操作。

下面是Java函数实现AVL树的删除操作。

public AVLNode delete(AVLNode root, int val) {
    if (root == null) {
        return null;
    }

    if (val < root.val) {
        root.left = delete(root.left, val);
    } else if (val > root.val) {
        root.right = delete(root.right, val);
    } else {
        // 如果找到了待删除节点
        if (root.left == null || root.right == null) {
            AVLNode temp = null;
            if (root.left == null) {
                temp = root.right;
            } else {
                temp = root.left;
            }

            // 没有子节点
            if (temp == null) {
                temp = root;
                root = null;
            } else {
                root = temp;
            }
        } else {
            AVLNode temp = minValueNode(root.right);
            root.val = temp.val;
            root.right = delete(root.right, temp.val);
        }
    }

    if (root == null) {
        return null;
    }

    // 更新节点的高度
    root.height = 1 + Math.max(height(root.left), height(root.right));

    // 计算节点的平衡因子
    int balance = getBalance(root);

    // LL情况,右旋
    if (balance > 1 && getBalance(root.left) >= 0) {
        return rightRotate(root);
    }

    // RR情况,左旋
    if (balance < -1 && getBalance(root.right) <= 0) {
        return leftRotate(root);
    }

    // LR情况,先左旋再右旋
    if (balance > 1 && getBalance(root.left) < 0) {
        root.left = leftRotate(root.left);
        return rightRotate(root);
    }

    // RL情况,先右旋再左旋
    if (balance < -1 && getBalance(root.right) > 0) {
        root.right = rightRotate(root.right);
        return leftRotate(root);
    }

    return root;
}

// 找到以节点为根的树中的最小值节点
private AVLNode minValueNode(AVLNode node) {
    AVLNode current = node;
    while (current.left != null) {
        current = current.left;
    }
    return current;
}

4. 总结

本文使用Java函数实现了AVL树的插入、删除、旋转等操作,代码简洁明了。AVL树的平衡性使得树的查找、插入、删除等操作都具有稳定的时间复杂度。在计算机科学中,AVL树是一种重要的数据结构,被广泛应用于数据库、编译器设计、文件系统等领域。