平衡二叉树(AVL树)
创建二叉排序树{1,2,3,4,5}时,左子树全部为空,查询速度明显降低,无法发挥二叉排序树的优势,所以需要平衡二叉树
平衡二叉树它的左右两个子树的高度差绝对值不超过1,并且它的左右两个子树也都是平衡二叉树。
当需要创建一颗AVL树的时候,往往需要__左旋转,右旋转,双旋转__
旋转方法添加在Node类中的add方法中
-
左旋转
当数列{4,3,6,5,7}加入8时,rightHight()-leftHight() > 1成立, 树就不是一个AVL树了
-
思路:
- 创建一个新的节点,值等于当前节点的值
- 将新节点的左子树设置为当前节点的左子树
- 将新节点的右子树设置为当前节点的右子树的左子树
- 把当前节点的值设置为右子节点的值
- 把当前节点的右子树设置为右子树的右子树
- 把当前节点的左节点设置为新节点
-
右旋转
思路和左旋转相同。
-
双旋转
有时不能实现一次单旋转完成二叉树的转换,需要双旋转。
当需要进行右旋转时,如果它的左子树的右子树高度大于左子树的左子树高度时,先对这个节点的左节点进行左旋转,在对当前节点进行右旋转。
代码实现:
package com.tree.AVL;
public class AVL_Tree {
public static void main(String[] args) {
AVLTree avlTree = new AVLTree();
// int[] arr = {4,3,6,5,7,8};
int[] arr = {10,11,7,6,8,9};
for (int i = 0; i < arr.length; i++) {
avlTree.add(new Node_(arr[i]));
}
System.out.println("树高度:");
System.out.println(avlTree.root.hight());
System.out.println("左右子树高度:");
System.out.println(avlTree.root.leftHight());
System.out.println(avlTree.root.rightHight());
//
}
}
//创建树
class AVLTree {
Node_ root;
public void add(Node_ node) {
if (root == null) {
root = node;
} else {
root.add(node);
}
}
//中序遍历
public void middleOrder() {
if (root != null) {
root.middleOrder();
} else {
System.out.println("null!!!");
}
}
//调用search方法
public Node_ search(int value) {
if (root == null) {
return null;
} else {
return root.search(value);
}
}
//调用searchParent
public Node_ searchParent(int value) {
if (root == null) {
return null;
} else {
return root.searchParent(value);
}
}
//寻找并删除最小子节点,返回最小子节点的值
public int delMin(Node_ node) {
Node_ target = node;
while (target.left != null) {
target = target.left;
}
del(target.value);
return target.value;
}
//删除节点
public void del(int value) {
Node_ targetNode = search(value);
if (targetNode == null) {
return;
}
if (root.left == null && root.right == null) {
root = null;
return;
}
Node_ targetNodeParent = searchParent(value);
//判断 1. 如果删除的是叶子节点——判断这个节点是左子节点还是右子节点,删除
if (targetNode.left == null && targetNode.right == null) {
if (targetNodeParent.left != null && targetNodeParent.left.value == value) {
targetNodeParent.left = null;
} else {
targetNodeParent.right = null;
}
} else if (targetNode.left != null && targetNode.right != null) {
//判断 2. 如果删除的是有两颗子树的节点——找到要删除节点的右子树的最小子节点,并使targetNode = 删去节点的值
int min = delMin(targetNode.right);
targetNode.value = min;
} else {
//判断 3. 如果删除只有一颗子树的节点——判断targetnodeParent的左子节点是targetNode还是右子节点是targetNode
if (targetNodeParent.left.value == targetNode.value) {
//目标节点是其父节点的左子节点
if (targetNode.left != null) {
targetNodeParent.left = targetNode.left;
} else {
targetNodeParent.left = targetNode.right;
}
} else {
//目标节点是其父节点的右子节点
if (targetNode.right != null) {
targetNodeParent.right = targetNode.right;
} else {
targetNodeParent.right = targetNode.left;
}
}
}
}
}
//创建节点
class Node_ {
int value;
Node_ left;
Node_ right;
public Node_(int value) {
this.value = value;
}
public void add(Node_ node) {
if (node.value < this.value) {
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);
}
}
//判断是否满足AVLtree
if(this.rightHight()-this.leftHight()>1){
if(right.leftHight()>right.rightHight()){
left.rightRotate();
}
leftRotate();
}
if(this.leftHight()-this.rightHight()>1){
if(left.rightHight()>left.leftHight()){
left.leftRotate();
}
rightRotate();
}
}
//计算以当前节点为根节点的树的高度
public int hight(){
return Math.max(left == null?0:left.hight(),right == null?0:right.hight())+1;
}
//左子树的高度
public int leftHight(){
if(left == null){
return 0;
}
return left.hight();
}
//右子树的高度
public int rightHight(){
if(right == null){
return 0;
}
return right.hight();
}
//找到要删去的节点
public Node_ search(int value) {
if (this.value == value) {
return this;
} else if (value < this.value) {
if (this.left == null) {
return null;
}
return this.left.search(value);
} else {
if (this.right == null) {
return null;
}
return this.right.search(value);
}
}
//找到要删除节点的父节点
public Node_ searchParent(int value) {
if ((this.left != null && this.left.value == value) || (this.right != null && this.right.value == value)) {
return this;
} else {
if (value < this.value && this.left != null) {
return this.left.searchParent(value);
} else if (value > this.value && this.right != null) {
return this.right.searchParent(value);
} else {
return null;
}
}
}
//中序遍历
public void middleOrder() {
if (this.left != null) {
this.left.middleOrder();
}
System.out.println(this.value);
if (this.right != null) {
this.right.middleOrder();
}
}
//左旋转
public void leftRotate(){
Node_ newNode = new Node_(value);
newNode.left = left;
newNode.right = right.left;
value = right.value;
right = right.right;
left = newNode;
}
//右旋转
public void rightRotate(){
Node_ newNode = new Node_(value);
newNode.right = right;
newNode.left = left.right;
value = left.value;
left = left.left;
right = newNode;
}
}