import java.util.ArrayList;
public class MyAVL<K extends Comparable<K>, V> {
private class Node{
public K key;
public V value;
public Node left, right;
public int high;
public Node(K key, V value){
this.key = key;
this.value = value;
high=1;
left = null;
right = null;
}
}
//返回节点的高度标注
private int getHigh(Node node){
if(node ==null)
return 0;
return node.high;
}
private Node root;
private int size;
public MyAVL(){
root = null;
size = 0;
}
public int getSize(){
return size;
}
public boolean isEmpty(){
return size == 0;
}
// 向二分搜索树中添加新的元素(key, value)
public void add(K key, V value){
root = add(root, key, value);
}
// 向以node为根的二分搜索树中插入元素(key, value),递归算法
// 返回插入新节点后二分搜索树的根
private Node add(Node node, K key, V value){
if(node == null){
size ++;
return new Node(key, value);
}
if(key.compareTo(node.key) < 0)
node.left = add(node.left, key, value);
else if(key.compareTo(node.key) > 0)
node.right = add(node.right, key, value);
else // key.compareTo(node.key) == 0
node.value = value;
//不论这个添加的点往那个子树上添加 都要更新高度标注 相等的话无影响
node.high = Math.max(getHigh(node.left),getHigh(node.right))+1;
//计算平衡因子并递归到根节点
int b = getB(node);
//LL 进行右旋转
if(b>1 && getB(node.left)>=0)//右旋转
return rightB(node);
//RR 左旋转
if (b<-1 && getB(node.right)<=0)
return leftB(node);
//LR 先对node.left进行左旋转 再对node右旋转
if(b>1 && getB(node.left)<0){
node.left=leftB(node.left);
return rightB(node);
}
//RL 先对右子树进行右旋转 再对node左旋转
if(b<-1 && getB(node.right)>=0){
node.right=rightB(node.right);
return leftB(node);
}
return node;
}
//左旋转操作 插入节点 在右孩子的右孩子
private Node leftB(Node node){
Node down =node.right;
Node one = down.left;
down.left=node;
node.right=one;
//维护高度
node.high = Math.max(getHigh(node.left),getHigh(node.right))+1;
down.high = Math.max(getHigh(down.left),getHigh(node.right))+1;
return down;
}
//右旋转操作 插入点在左孩子的左节点
private Node rightB(Node node){
Node down=node.left;
Node one = down.right;
down.right=node;
node.left=one;
//维护高度
node.high = Math.max(getHigh(node.left),getHigh(node.right))+1;
down.high = Math.max(getHigh(down.left),getHigh(down.right))+1;
return down;
}
//方法 判断当前tree是不是二分搜索树 满足中大于左小于右
public boolean isBST(){
ArrayList<K> list= new ArrayList<>();
isBST(root,list);
//遍历list判断是否有序
for(int i=1;i<list.size();i++)
if(list.get(i-1).compareTo(list.get(i))>0)
return false;
return true;
}
//返回当前节点的 平衡因子
public int getB(Node node){
//不需要取绝对值,后期要判断左旋转还是右旋转
return getHigh(node.right)-getHigh(node.left);
}
//判断树是不是平衡树
public boolean isB(){
return isB(root);
}
private boolean isB(Node node){
//终止条件
if(node==null)
return true;
//判断当前节点 平衡因子
if(Math.abs(getB(node))>1)
return false;
//左右子孩子平衡因子
return isB(node.left)&&isB(node.right);
}
private void isBST(Node node,ArrayList list){
//递归遍历
if(node == null)
return;
isBST(node.left,list);
list.add(node.key);
isBST(node.right,list);
}
// 返回以node为根节点的二分搜索树中,key所在的节点
private Node getNode(Node node, K key){
if(node == null)
return null;
if(key.equals(node.key))
return node;
else if(key.compareTo(node.key) < 0)
return getNode(node.left, key);
else // if(key.compareTo(node.key) > 0)
return getNode(node.right, key);
}
public boolean contains(K key){
return getNode(root, key) != null;
}
public V get(K key){
Node node = getNode(root, key);
return node == null ? null : node.value;
}
public void set(K key, V newValue){
Node node = getNode(root, key);
if(node == null)
throw new IllegalArgumentException(key + " doesn't exist!");
node.value = newValue;
}
// 返回以node为根的二分搜索树的最小值所在的节点
private Node minimum(Node node){
if(node.left == null)
return node;
return minimum(node.left);
}
// 删除掉以node为根的二分搜索树中的最小节点
// 返回删除节点后新的二分搜索树的根
private Node removeMin(Node node){
if(node.left == null){
Node rightNode = node.right;
node.right = null;
size --;
return rightNode;
}
node.left = removeMin(node.left);
return node;
}
// 从二分搜索树中删除键为key的节点
public V remove(K key){
Node node = getNode(root, key);
if(node != null){
root = remove(root, key);
return node.value;
}
return null;
}
private Node remove(Node node, K key){
if( node == null )
return null;
Node del;
if( key.compareTo(node.key) < 0 ){
node.left = remove(node.left , key);
del= node;
}
else if(key.compareTo(node.key) > 0 ){
node.right = remove(node.right, key);
del = node;
}
else{ // key.compareTo(node.key) == 0
// 待删除节点左子树为空的情况
if(node.left == null){
Node rightNode = node.right;
node.right = null;
size --;
del = rightNode;
}
// 待删除节点右子树为空的情况
else if(node.right == null){
Node leftNode = node.left;
node.left = null;
size --;
del= leftNode;
}else{
// 待删除节点左右子树均不为空的情况
// 找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
// 用这个节点顶替待删除节点的位置
Node successor = minimum(node.right);
successor.right = remove(node.right,successor.key);
successor.left = node.left;
node.left = node.right = null;
del= successor;
}
}
if(del==null)
return null;
del.high = Math.max(getHigh(del.left),getHigh(del.right))+1;
//计算平衡因子并递归到根节点
int b = getB(del);
//LL 进行右旋转
if(b>1 && getB(del.left)>=0)//右旋转
return rightB(del);
//RR 左旋转
if (b<-1 && getB(del.right)<=0)
return leftB(del);
//LR 先对node.left进行左旋转 再对node右旋转
if(b>1 && getB(del.left)<0){
del.left=leftB(del.left);
return rightB(del);
}
//RL 先对右子树进行右旋转 再对node左旋转
if(b<-1 && getB(del.right)>=0){
del.right=rightB(del.right);
return leftB(del);
}
return del;
}
}