平衡二叉树(AVL)

216 阅读8分钟

二叉搜索树会有可能出现极左/右的情况,平衡二叉树,在该基础上增加了深度判断,如果左右两边的子树深度差==2的情况下,旋转失去平衡的二叉树。使整课树都是平衡的状态,时间的复杂度为o(logn)。

旋转的四种情况

旋转情况1

旋转情况2

旋转情况3

旋转情况4

代码实现

TreeNode

public class BalanceTreeNode {
    public int value;
    public BalanceTreeNode right;
    public BalanceTreeNode left;
    public int height = 1;  // 处理平衡的高度
    public BalanceTreeNode(int value) {
        this.value = value;
    }
}
    private BalanceTreeNode root;
    public void put(int value) {
        root = add(root, value);
    }
    public void remove(int value) {
        root = remove(root, value);
    }
//和添加处理一直,但是左右相反。
    private BalanceTreeNode remove(BalanceTreeNode node, int value) {
        if (node == null) {
            return null;
        }
        if (value > node.value) {
            node.right = remove(node.right, value);
            int leftHeight = getHeight(node.left);
            int rightHeight = getHeight(node.right);
//删除右边的节点,那么左边的节点大于右边的节点,失去平衡的情况下,进行旋转            
            if (leftHeight - rightHeight == 2) {
	    // 如果出现“情况3”的情况,先对左孩子进行左旋,在右旋
                if (getHeight(node.left.right) > getHeight(node.left.left)) {
                    node = L_R_Ration(node);
                } else {
                    node = L_Rotation(node);
                }
            }
        } else if (value < node.value) {
            node.left = remove(node.left, value);
            int leftHeight = getHeight(node.left);
            int rightHeight = getHeight(node.right);
            if (rightHeight - leftHeight == 2) {
                if (getHeight(node.right.left) > getHeight(node.right.right)) {
                    node = R_L_Ration(node);
                } else {
                    node = R_Rotation(node);
                }
            }
        } else {
            if (node.right == null && node.left == null) {
                node = null;
                return null;
            } else if (node.right == null && node.left != null) {
                BalanceTreeNode left = node.left;
                node = null;
                return left;
            } else if (node.right != null && node.left == null) {
                BalanceTreeNode right = node.right;
                node = null;
                return right;
            } else {
                // 在左边查找最大的节点
                BalanceTreeNode maxNode = maxNode(node.left);
                maxNode.left = delMaxNode(node.left);
                maxNode.right = node.right;
                node = null;
                return maxNode;
            }

        }

        node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
        return node;
    }
    private BalanceTreeNode delMaxNode(BalanceTreeNode node) {
        if (node != null) {
            BalanceTreeNode leftNode = node.left;
            node = null;
            return leftNode;
        }
        node = delMaxNode(node.right);
        return node;
    }
    private BalanceTreeNode maxNode(BalanceTreeNode node) {
        if (node.right == null) {
            return node;
        }
        return maxNode(node.right);
    }
    private BalanceTreeNode add(BalanceTreeNode node, int value) {
        if (node == null) {
            BalanceTreeNode newNode = new BalanceTreeNode(value);
            return newNode;
        }
		// 放在节点的右边
        if (value > node.value) {
            node.right = add(node.right, value);
            int leftHeight = getHeight(node.left);
            int rightHeight = getHeight(node.right);
			// 当右子树的高度大于左子树的高度
            if (rightHeight - leftHeight == 2) {
				//如果出现“情况4”的状况,先对右孩子进行右旋
                if (getHeight(node.right.left) > getHeight(node.right.right)) {
                    node = R_L_Ration(node);
                } else {
				// 否则进行左旋
                    node = L_Rotation(node);
                }
            }
        } else if (value < node.value) { // 放在节点的左边
            node.left = add(node.left, value);
            int leftHeight = getHeight(node.left);
            int rightHeight = getHeight(node.right);
			// 当左边的高度大于右边的高度 进行旋转
            if (leftHeight - rightHeight == 2) {
			// 如果出现“情况3”的情况,先对左孩子进行左旋,在右旋
                if (getHeight(node.left.right) > getHeight(node.left.left)) {
                    node = L_R_Ration(node);
                } else {
					// 否则直接进行右旋
                    node = R_Rotation(node);
                }
            }
        } else {
            node.value = value;
        }
        node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
        return node;
    }
    private BalanceTreeNode L_R_Ration(BalanceTreeNode node) {
        node.left = L_Rotation(node.left);
        return R_Rotation(node);
    }
    private BalanceTreeNode R_L_Ration(BalanceTreeNode node) {
		//右旋
        node.right = R_Rotation(node.right);
		//在左旋
        return L_Rotation(node);
    }

    private BalanceTreeNode R_Rotation(BalanceTreeNode node) {
        BalanceTreeNode left = node.left;
        BalanceTreeNode rigth = left.right;
        left.right = node;
        node.left = rigth;

        node.height = Math.max(getHeight(node.left), getHeight(node.right));
        left.height = Math.max(getHeight(left.left), getHeight(left.right));
        return left;
    }
    private BalanceTreeNode L_Rotation(BalanceTreeNode node) {
        BalanceTreeNode right = node.right;
        BalanceTreeNode left = right.left;
        right.left = node;
        node.right = left;
        node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
        right.height = Math.max(getHeight(right.left), getHeight(right.right)) + 1;
        return right;
    }
    private int getHeight(BalanceTreeNode node) {
        return node == null ? 0 : node.height;
    }
    public void print() {
        LinkedList<BalanceTreeNode> linkedList = new LinkedList<>();
        if (root != null) {
            linkedList.push(root);
        }
        while (!linkedList.isEmpty()) {
            BalanceTreeNode BalanceTreeNode = linkedList.pop();
            System.out.print(BalanceTreeNode.value);
            if (BalanceTreeNode.left != null) {
                linkedList.add(BalanceTreeNode.left);
            }
            if (BalanceTreeNode.right != null) {
                linkedList.add(BalanceTreeNode.right);
            }
        }
    }
    public static void main(String[] args) {
        SearchBalanceTree tree = new SearchBalanceTree();
        tree.put(3);
        tree.put(2);
        tree.put(5);
        tree.put(4);
        tree.remove(2);
        tree.print();
    }
}