public class AVLTree<T> {
AvlNode<T> root;//树根
public void insert(int key,T value){
root = insert(root,key,value);
}
public AvlNode<T> insert(AvlNode<T> node,int key,T value){
//没有节点就创建节点
if(node == null){
node = new AvlNode<T>(key, value);
updateBalanceFactor(node);
return node;
}
if(key < node.key){
//递归的寻找可以插入的节点,如果键比当前节点的键小,就继续递归的寻找
node.leftChild = insert(node.leftChild, key, value);
//插入操作后检查平衡因子
updateBalanceFactor(node);
//检查当前的平衡因子,如果平衡因子大于1,就说明左支过重了,因为是递归插入,只会有左支过重,所以不会有右支过重
if(node.balanceFactor > 1){
//如果左孩子的平衡因子大于1,就说明左边的节点比又变多,就是左左类型,要使用右单旋,否则就是用左右双旋
if(node.leftChild.balanceFactor > 0){
node = rightRotate(node);
}else{
node =leftRightRotate(node);
}
}
}else if(key > node.key){
//递归的寻找可以插入的节点,如果键比当前节点的键大,就继续递归的寻找
node.rightChild = insert(node.rightChild, key, value);
//插入操作后检查平衡因子
updateBalanceFactor(node);
if(node.balanceFactor < -1){
//如果当前节点的右孩子的平衡因子小于-1,就说明右支过重了
if(node.balanceFactor < -1){
//如果当前节点的右孩子的平衡因子小于0,就说明是右右类型,就左单旋,否则就右左双旋
if(node.rightChild.balanceFactor < 0){
node = leftRotate(node);
}else{
node = rightLeftRotate(node);
}
}
}
}
//跟新平衡因子,并返回节点
updateBalanceFactor(node);
return node;
}
public void delete(int key){
root = delete(root, key);
}
private AvlNode<T> delete(AvlNode<T> node,int key){
if(node == null){
return node;
}
//如果值小于当前节点的值就递归下去继续删
if(key < node.key){
//递归查询左节点,删除后返回完整的左支
node.leftChild = delete(node.leftChild, key);
updateBalanceFactor(node);
//如果递归删除后树不平衡了,就要旋转节点
if(node.balanceFactor > 1 ){
if(node.leftChild.balanceFactor > 0){
node = rightRotate(node);
}else{
node = leftRightRotate(node);
}
}else if(node.balanceFactor < -1){
if(node.rightChild.balanceFactor < 0){
node = leftRotate(node);
}else{
node = rightLeftRotate(node);
}
}
//如果值大于当前节点的值就递归下去继续删
}else if(key > node.key){
node.rightChild = delete(node.rightChild, key);
updateBalanceFactor(node);
//删除后不平衡就旋转节点
if(node.balanceFactor > 1 ){
if(node.leftChild.balanceFactor > 0){
node = rightRotate(node);
}else{
node = leftRightRotate(node);
}
}else if(node.balanceFactor < -1){
if(node.rightChild.balanceFactor < 0){
node = leftRotate(node);
}else{
node = rightLeftRotate(node);
}
}
//如果找到了要删除的节点,并且节点左右儿子都不为空
}else if(node.leftChild != null && node.rightChild != null){
//判断平衡因子,不能加剧失衡,替换为多的哪一支
if(node.balanceFactor > 1){
//左支更深,用左支最大的节点替换
AvlNode<T> max = max(node.leftChild);
node.key = max.key;
node.data = max.data;
//递归找到并删除节点,因为是递归思想,所以默认删除后获取的节点都是平衡的
node.leftChild = delete(node.leftChild, max.key);
//操作后更新平衡因子
}else{
//否则就拿右节点中最大的节点替换
AvlNode<T> min = min(node.rightChild);
node.key = min.key;
node.data = min.data;
node.rightChild = delete(node.rightChild,min.key);
}
//更新平衡因子,如果不平衡就旋转节点
updateBalanceFactor(node);
if(node.balanceFactor > 1 ){
if(node.leftChild.balanceFactor > 0){
node = rightRotate(node);
}else{
node = leftRightRotate(node);
}
}else if(node.balanceFactor < -1){
if(node.rightChild.balanceFactor < 0){
node = leftRotate(node);
}else{
node = rightLeftRotate(node);
}
}
}else{
//删除叶节点或者只有一个儿子的节点,因为avl树定义,所以无论如何删除都不会引起本层的不平衡。
node = node.rightChild !=null ? node.rightChild:node.leftChild;
return node;
}
updateBalanceFactor(node);
return node;
}
/** * 更新平衡因子 * @param node */
private void updateBalanceFactor(AvlNode<T> node){
//左子树的深度
int liftChildHight = getHight(node.leftChild);
//右子树的深度
int rightChildHight = getHight(node.rightChild);
//更新树深
node.hight = Math.max(liftChildHight, rightChildHight) + 1;
//平衡因子为左子树的深度-右子树的深度
node.balanceFactor = liftChildHight - rightChildHight;
}
/** * 右重,左单旋 */
private AvlNode<T> leftRotate(AvlNode<T> node){
//新节点树,就是之前的右孩子节点
AvlNode<T> newNode = node.rightChild;
//拿右孩子左补自己的右
node.rightChild = newNode.leftChild;
//拿自己补孩子的左
newNode.leftChild = node;
//更新节点平衡因子
updateBalanceFactor(node);
updateBalanceFactor(newNode);
//返回旋转后的节点
return newNode;
}
/** * 左重,右单旋 * @param node * @return */
private AvlNode<T> rightRotate(AvlNode<T> node){
//新节点树,之前的左节点
AvlNode<T> newNode = node.leftChild;
//拿左孩子的右孩子补自己的左节点
node.leftChild = newNode.rightChild;
//拿自己补孩子的右节点
newNode.rightChild = node;
updateBalanceFactor(node);
updateBalanceFactor(newNode);
return newNode;
}
/** * 右重,右左双旋,先孩子右,后自己左 * @param node * @return */
private AvlNode<T> rightLeftRotate(AvlNode<T> node){
//孩子右旋,自己左旋
node.rightChild = rightRotate(node.rightChild);
return leftRotate(node);
}
/** * 左重,左右双旋,先孩子左,后自己右 * @param node * @return */
private AvlNode<T> leftRightRotate(AvlNode<T> node){
node.leftChild = leftRotate(node.leftChild);
return rightRotate(node);
}
/** * 求树高 * @param node * @return */
private int getHight(AvlNode<T> node){
return node == null?0:node.hight;
}
/** * 获最小的一个节点 * @param node * @return */
private AvlNode<T> min(AvlNode<T> node){
if(node == null){
return null;
}else if(node.leftChild == null){
return node;
}
return min(node.leftChild);
}
/** * 中序遍历 * @param node */
/** * 获取最大的一个节点 * @param node * @return */
private AvlNode<T> max(AvlNode<T> node){
if(node == null){
return null;
}else if(node.rightChild == null){
return node;
}
return max(node.rightChild);
}
/** * 中序遍历 * @param node */
public void middleOrder(AvlNode<T> node){
if(node == null){
return ;
}
middleOrder(node.leftChild);
System.out.println("key:"+node.key+",vlaue:"+node.data);
middleOrder(node.rightChild);
}
/** * avl树节点 * @author yuli * * @param <T> */
private static class AvlNode <T>{
int key;
T data;
int hight;//树的高度
int balanceFactor;//平衡因子,左子树的高度-右子树的高度,只能为1,0,-1
AvlNode<T> leftChild;//左子树
AvlNode<T> rightChild;//右子树
AvlNode(int key,T data){
this.key = key;
this.data = data;
}
}
}
avl树的完整实现
原文作者:AVL树
原文地址: https://blog.csdn.net/yulio1234/article/details/77493902
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/yulio1234/article/details/77493902
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。