目的:提高查找效率
判断平衡:任意一个结点的左子树和右子树的高度差不能超过绝对值1
平衡因子:1,0,-1
如何平衡:旋转
左旋
- 失衡结点的右孩子代替结点的位置
- 右孩子的左子树变成失衡结点的右子树
- 该失衡结点变成它右孩子的左子树
右旋
- 失衡结点的左孩子代替它的位置
- 失衡结点的左孩子的右子树变成失衡结点的左子树
- 失衡结点变成左孩子的右子树
插入情况分析:
- 如果插入的结点在失衡结点的左孩子的左子树上面,只进行一次右旋
- 当插入的结点在失衡结点的左孩子的右子树上面(如果进行右旋,右子树在右旋第二步变成了失衡结点的左子树,加上第三步把失衡结点连为右子树相当于又多加了一层,导致依旧失衡),先进行失衡结点左孩子的左旋,再进行失衡结点的右旋(注意旋点)
- 如果插入的结点在失衡结点的右孩子的右子树上面,只进行一次左旋
- 当插入的结点在失衡结点的右孩子的左子树上面,先进行失衡结点右孩子的右旋,再进行失衡结点左旋
删除情况分析:
- 删除的结点是叶子结点
- 删除的结点只有左子树
- 删除的结点只有右子树
- 删除的结点既有左子树又有右子树
package Tree.AVLTree;
import java.util.ArrayList;
import java.util.List;
public class AVLTree {
public AVLTreeNode root;
/**
* 获得结点高度
*
* @param node 指定结点
* @return 结点高度
*/
public int getHeight(AVLTreeNode node) {
if (node == null) {
return 0;
}
int left= (node.leftNode == null ? 0 : node.leftNode.height) ;
int right=(node.rightNode == null ? 0 : node.rightNode.height);
return Math.max(left,right);
}
public void insert(int data) {
root = insert(data, root);
}
/**
* 递归插入结点,需要每层判断是否平衡
*
* @param data 插入的结点的值
*/
public AVLTreeNode insert(int data, AVLTreeNode node) {
if (node == null) {
node = new AVLTreeNode(data);
}
if (data < node.data) {
node.leftNode = insert(data, node.leftNode);
//作为左子树插入,只可能左子树高
if (getHeight(node.leftNode) - getHeight(node.rightNode) == 2) {
if (data < node.leftNode.data) {
//左子树的左孩子,右旋
node = rightRotate(node);
} else{
//左子树的右孩子,先左旋再右旋
node = leftRightRotate(node);
}
}
}
if(data>node.data){
node.rightNode = insert(data,node.rightNode);
//作为右子树插入,只可能右子树高
if(getHeight(node.rightNode)-getHeight(node.leftNode)==2){
if(data<node.rightNode.data){
node = rightLeftRotate(node);
} else{
node = leftRotate(node);
}
}
}
//更新结点高度
node.height = getHeight(node) + 1;
return node;
}
/**
* 右旋
* @param node 失衡结点
* @return 平衡之后的结点
*/
public AVLTreeNode rightRotate(AVLTreeNode node){
AVLTreeNode leftNode = node.leftNode;
//失衡结点的左孩子的右子树变成失衡结点的左子树
node.leftNode = leftNode.rightNode;
//失衡结点变成左孩子的右子树
leftNode.rightNode = node;
node.height = getHeight(node) + 1;
leftNode.height = getHeight(leftNode) + 1;
return leftNode;
}
/**
* 左旋
* @param node 失衡结点
* @return 平衡之后的结点
*/
public AVLTreeNode leftRotate(AVLTreeNode node){
AVLTreeNode rightNode = node.rightNode;
node.rightNode = rightNode.leftNode;
rightNode.leftNode = node;
node.height = getHeight(node) + 1;
rightNode.height=getHeight(rightNode) + 1;
return rightNode;
}
/**
* 先左旋再右旋
* @param node 失衡结点
* @return 平衡之后的结点
*/
public AVLTreeNode leftRightRotate(AVLTreeNode node){
node.leftNode = leftRotate(node.leftNode);
node = rightRotate(node);
return node;
}
/**
* 先右旋再左旋
* @param node 失衡结点
* @return 平衡之后的结点
*/
public AVLTreeNode rightLeftRotate(AVLTreeNode node){
node.rightNode = rightRotate(node.rightNode);
node = leftRotate(node);
return node;
}
public AVLTreeNode deleteNode(int data){
return deleteNode(data,root);
}
/**
* 删除结点
* @param data 要删除的结点值
* @param node 结点
* @return
*/
public AVLTreeNode deleteNode(int data,AVLTreeNode node){
if(node == null){
return null;
}
if(data < node.data){
node.leftNode = deleteNode(data,node.leftNode);
if(getHeight(node.rightNode)-getHeight(node.leftNode)==2){
if(getHeight(node.rightNode.leftNode)>getHeight(node.rightNode.rightNode)){
node = rightLeftRotate(node);
} else{
node = leftRotate(node);
}
}
} else if(data > node.data){
node.rightNode = deleteNode(data,node.rightNode);
if(getHeight(node.leftNode)-getHeight(node.rightNode)==2){
if(getHeight(node.leftNode.rightNode)>getHeight(node.leftNode.leftNode)){
node = leftRightRotate(node);
} else{
node = rightRotate(node);
}
}
} else if(node.leftNode !=null&&node.rightNode != null){
//删除的结点既有左子树也有右子树
node.data = findMin(node.rightNode).data;
node.rightNode = deleteNode(node.data,node.rightNode);
} else {
//删除的结点只有一个孩子或者为叶子结点
node = (node.leftNode != null) ? node.leftNode : node.rightNode;
}
node.height = getHeight(node) + 1;
return node;
}
/**
* 找到最小的结点
* @param node 指定结点的右节点
* @return 目标结点
*/
public AVLTreeNode findMin(AVLTreeNode node){
if(node.leftNode == null){
return node;
}else{
return findMin(node.leftNode);
}
}
}