先介绍一个概念:
Height balance property: For every internal node v of T, the height of the children of v differs by 1 at most. 每个子结点的高度差最多为1.
符合Height balance property的BST叫做AVL Tree,平衡二叉树。
对于一个有n个节点的平衡二叉树来说,它的高度是O(logn),证明参考:点击打开链接
AVL的插入操作与BST的插入操作相似,之后还要再进行一步判断Tree 是否达到平衡。这里引入函数getBalance返回左右子节点的高度差。设Z是我们判断的对象,y是z在插入路径上的子节点,x是插入路径上的孙子节点。判断的结果通常为以下4种:
- left left case : we need to right rotate the tree for once
- left right case: First, we need to right rotate the tree, then to left rotate the tree
- right right case : we need to left rotate the tree for once
- right left case: First, we need to left rotate the tree, then to right rotate the tree
insert()方法
public int height(Node node){ if (node == null) return 0; return node.height; } public Node leftRotate(Node node){ Node y = node.right; Node T2 = y.left; y.left = node; node.right = T2; node.height = Math.max(height(node.left),height(node.right)); y.height = Math.max(height(y.left), height(y.right)); return y; } public Node rightRotate(Node node){ Node x = node.left; Node T1 = x.right; x.right = node; node.left = T1; node.height = Math.max(height(node.left),height(node.right)); x.height = Math.max(height(x.left), height(x.right)); return x; } public int getBalance(Node node){ if (node == null){ return 0; } return height(node.left) - height(node.right); } public Node insert(Node node, int key){ if (node == null){ return (new Node(key)); } if (key < node.key){ node.left = insert(node.left,key); } else if (key > node.key){ node.right = insert(node.right,key); } else { return node; } node.height = 1 + Math.max(height(node.left), height(node.right)); int balance = getBalance(node); // Left Left case if (balance > 1 && key < node.left.key){ return rightRotate(node); } // Right Right case if (balance < -1 && key > node.right.key){ return leftRotate(node); } // Left right case if (balance > 1 && key > node.left.key){ node.left = leftRotate(node.left); return rightRotate(node); } // Right left case if (balance < -1 && key < node.right.key){ node.right = rightRotate(node.right); return leftRotate(node); } return node; }
delete()方法,与BST中的delete相似,在执行了delete操作之后需要检查tree是否达到balanced状态,引入平衡因子balance和getBalance()方法。在AVL Tree中的insert和delete都用到了递归,可以画stack图来加深对递归的理解。比如insert中,每执行一次递归,都会增加一个stack frame用于执行insert方法,一直到node == null,返回新建的node。stack frame从上往下逐层消失,返回值一层一层往下递送。
public Node deleteNode(Node root, int key){ if (root == null){ return root; } if (key < root.key){ root.left = deleteNode(root.left,key); } else if (key > root.key){ root.right = deleteNode(root.right,key); } else { if (root.left == null || root.right == null){ Node temp = null; if (root.left == temp){ temp = root.right; } else { temp =root.left; } if (temp == null){ temp = root; root = null; } } else { //node with two children Node temp = getReplacement(root.right); root.key = temp.key; root.right = deleteNode(root.right,temp.key); } } if (root == null){ return root; } root.height = Math.max(height(root.left),height(root.right)); int balance = getBalance(root); if (balance > 1 && getBalance(root.left) >= 0){ return rightRotate(root); } if (balance > 1 && getBalance(root.left) < 0){ root.left = leftRotate(root.left); return rightRotate(root); } if (balance < -1 && getBalance(root.right) <= 0){ return leftRotate(root); } if (balance < -1 && getBalance(root.right) > 0){ root.right = rightRotate(root.right); return leftRotate(root); } return root; }