目录
1.简单介绍
- 平衡二叉树也叫平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树,可以保证查询效率较高。
- 特点:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
2.左旋转
- 存在一个不平衡的二叉树,其中某个节点的右子树的高度远大于其左子树的高度 ,左旋的目的是将节点向左旋转,使其成为新根节点,并保持树的平衡
- 步骤:
- 1.创建新的结点,以当前根结点的值
- 2.把新的结点的左子树设置成当前结点的左子树
- 3.把新的结点的右子树设置成当前节点的右子树的左子树
- 4.把当前结点的值替换成右子结点的值
- 5.把当前结点的右子树设置成当前结点右子树的右子树
- 6.把当前结点的左子树(左子结点)设置成新的结点
3.左旋代码实现
/** * 左旋 */ private void leftRotate() { //创建新的结点,以当前根结点的值 Node newNode = new Node(this.id); //把新的结点的左子树设置成当前结点的左子树 newNode.left = this.left; //把新的结点的右子树设置成带你过去结点的右子树的左子树 newNode.right = this.right.left; //把当前结点的值替换成右子结点的值 this.id = this.right.id; //把当前结点的右子树设置成当前结点右子树的右子树 this.right = this.right.right; //把当前结点的左子树(左子结点)设置成新的结点 this.left = newNode; }
4.右旋
- 存在一个不平衡的二叉树,其中某个节点的左子树的高度远大于其右子树的高度 ,右旋的目的是将节点向右旋转,使其成为新根节点,并保持树的平衡
- 步骤:
- 1.创建新的结点,以当前根结点的值
- 2.把新的结点的右子树设置成当前结点的右子树
- 3.把新的结点的左子树设置当前结点的左子树的右子树
- 4.把当前结点的值替换成左子结点的值
- 5.把当前结点的左子树设置成当前结点左子树的左子树
- 6.把当前结点的右子树(右子结点)设置成新的结点
5.右旋代码实现
/** * 左旋 */ private void rightRotate() { //创建新的结点,以当前根结点的值 Node newNode = new Node(this.id); //把新的结点的右子树设置成当前结点的右子树 newNode.right = this.right; //把新的结点的左子树设置当前结点的左子树的右子树 newNode.left = this.left.right; //把当前结点的值替换成左子结点的值 this.id = this.left.id; //把当前结点的左子树设置成当前结点左子树的左子树 this.left = this.left.left; //把当前结点的右子树(右子结点)设置成新的结点 this.right = newNode; }
6.双旋转
- 当满足左旋转时,他的左子树的右子树高度大于左子树高度,旋转后依然不是平衡树
- 当满足右旋转时,他的右子树的左子树高度大于右子树高度,旋转后依然不是平衡树
- 步骤:
- 1.先旋转当前节点的左节点(右节点),再对当前节点进行右旋(左旋)
7.双旋转代码实现
/** * 递归添加 */ public void add(Node node) { if (node == null) { return; } if (node.id < this.id) { if (this.left == null) { this.left = node; } else { this.left.add(node); } } else { if (this.right == null) { this.right = node; } else { this.right.add(node); } } //当添加完节点后,满足右子树的高度-左子树的高度的 >1,进行左旋 if (rightHeight() - leftHeight() > 1) { if (right != null && right.leftHeight() > right.rightHeight()) { //先对当前节点的右子树进行左旋 right.rightRotate(); //在对当前节点进行左旋 leftRotate();//左旋 } else { //直接左旋 leftRotate(); } return; } //当添加完节点后,满足左子树的高度的-右子树的高度 >1,进行右旋 if (leftHeight() - rightHeight() > 1) { //如果它的左子树的右子树高度大于它的左子树的高度 if (left != null && left.rightHeight() > left.leftHeight()) { //先对当前节点的左子树进行左旋 left.leftRotate(); //再对当前节点进行右旋 rightRotate(); } else { //直接右旋 rightRotate(); } } }