import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class AVLTree<K extends Comparable<K>,V> {
private class Node{
public K key;
public V val;
public Node left;
public Node right;
public int height;//节点高度
public Node(K key,V val) {
// TODO 自动生成的构造函数存根
this.key=key;
this.val=val;
this.left=null;
this.right=null;
this.height=1;//默认新的节点高度值为1
}
}
private int size;//节点个数
private Node root;//根节点
public AVLTree() {
// TODO 自动生成的构造函数存根
root=null;
size=0;
}
public int getSize() {
return size;
}
//计算节点的高度
private int getHeight(Node cur) {
if(cur==null)//空节点高度为0
return 0;
return cur.height;
}
//计算节点的平衡因子
//左子树比右子树高为正,反之为负
private int getBalanceFactor(Node cur) {
if(cur==null)
return 0;
return getHeight(cur.left)-getHeight(cur.right);
}
public boolean isEmpty() {
return size==0;
}
//添加节点
public void add(K key,V val) {
root=add(key,val,root);
}
//返回插入新节点后的二叉树的根
private Node add(K key,V val,Node node) {
if(node==null) {
size++;
return new Node(key,val);
}
if(key.compareTo(node.key)<0) {//小往左
node.left=add(key,val,node.left);
}else if(key.compareTo(node.key)>0) {//大往右
node.right=add(key,val,node.right);
}else
node.val=val;//相等 更新Val值
//平衡维护后返回
return toBalance(node);
}
//返回维护好平衡的根节点
private Node toBalance(Node cur) {
//0、更新高度值
cur.height=1+Math.max(getHeight(cur.left), getHeight(cur.right));
//1、计算本节点的平衡因子
int balanceFactor=getBalanceFactor(cur);
//2、平衡维护
//(1)新插入的节点在本节点左孩子的左侧
if(balanceFactor>1&&getBalanceFactor(cur.left)>=0)
return rightRotate(cur);
//(2)新插入节点在本节点右孩子的右侧
if(balanceFactor<-1&&getBalanceFactor(cur.right)<=0)
return leftRotate(cur);
//(3)新插入的节点在本节点左孩子的右侧
// cur cur cLR
// / \ / \ 对cur右旋转 / \
// cur.left(cL) a cLR a --> cL cur
// / \ 对cL左旋转 / \ / \ / \
// c cLR --> cL b c d b a
// / \ /\
// d b c d
if(balanceFactor>1&&getBalanceFactor(cur.left)<=0) {
cur.left=leftRotate(cur.left);
return rightRotate(cur);
}
//(4)新插入的节点在本节点右孩子的左侧
if(balanceFactor<-1&&getBalanceFactor(cur.right)>=0) {
cur.right=rightRotate(cur.right);
return leftRotate(cur);
}
return cur;
}
//当插入节点在本节点左子树的左侧时,进行右旋转
// cur cur.left(cL)
// / \ / \
// cur.left(cL) a --> new cur
// / \ / \
// new cL.right(cLR) cL.right(cLR) a
private Node rightRotate(Node cur) {
Node cL=cur.left;;
cur.left=cL.right;
cL.right=cur;
//更新高度
cur.height=1+Math.max(getHeight(cur.left), getHeight(cur.right));
cL.height=1+Math.max(getHeight(cL.left), getHeight(cL.right));
return cL;
}
//当插入节点在本节点右子树的右侧时,进行左旋转
// cur cur.right(cR)
// / \ / \
// a cur.right(cR) --> cur new
// / \ / \
// cR.left(cRL) new a cR.left(cRL)
private Node leftRotate(Node cur) {
Node cR=cur.right;
cur.right=cR.left;
cR.left=cur;
//更新高度
cur.height=1+Math.max(getHeight(cur.left),getHeight(cur.right));
cR.height=1+Math.max(getHeight(cR.left), getHeight(cR.right));
return cR;
}
//判断是否为一棵二叉树
public boolean isBST() {
ArrayList<K> keys=new ArrayList<K>();
//中序遍历整棵树,结果存在数组中,若满足二叉树性质,中序遍历之后数组中元素从小到大排列。
inOrder(root,keys);
//如果数组前一个元素大于后一个元素,说明不是一棵二叉树。
for(int i=1;i<keys.size();i++)
if(keys.get(i-1).compareTo(keys.get(i))>0)
return false;
return true;
}
//将这棵树中序遍历后放入数组
private void inOrder(Node node,ArrayList<K>keys) {
if(node==null)
return;
inOrder(node.left,keys);
keys.add(node.key);
inOrder(node.right,keys);
}
//判断当前的二叉树是否是平衡二叉树
public boolean isBalance() {
return isBalance(root);
}
//辅助函数
private boolean isBalance(Node cur) {
if(cur==null)
return true;
int balanceFactor=getBalanceFactor(cur);//获取平衡因子
if(Math.abs(balanceFactor)>1)//如果平衡因子的绝对值大于1,则不平衡
return false;
return isBalance(cur.left)&&isBalance(cur.right);
}
//查询节点中是否包含某个元素
public boolean contains(K key) {
return contains(root,key);
}
private boolean contains(Node node ,K key) {
if(node==null)
return false;
if(node.key.compareTo(key)==0)
return true;
else if(key.compareTo(node.key)>0)
return contains(node.right,key);
else
return contains(node.left,key);
}
//前序遍历
public void preOrder() {
preOrder(root);
}
private void preOrder(Node node) {
if (node==null)
return ;
//先处理本节点,再处理左右(这里做打印处理
System.out.println(node.key+","+node.val);
preOrder(node.left);
preOrder(node.right);
}
//前序遍历非递归实现
public void preOrderNR() {
Stack<Node> stack=new Stack<>();
stack.push(root);
while(!stack.isEmpty()) {
Node cur=stack.pop();
System.out.println(cur.key+","+cur.val);
if(cur.right!=null)
stack.push(cur.right);
if(cur.left!=null)
stack.push(cur.left);
}
}
//中序遍历
public void inOrder() {
inOrder(root);
}
private void inOrder(Node node) {
if(node==null)
return;
inOrder(node.left);
System.out.println(node.key+","+node.val);
inOrder(node.right);
}
//后续遍历
public void postOrder() {
postOrder(root);
}
private void postOrder(Node node) {
if(node==null)
return;
postOrder(node.left);
postOrder(node.right);
System.out.println(node.key+","+node.val);
}
//层序遍历
public void levelOrder() {
Queue<Node> q=new LinkedList<>();
q.add(root);
while(!q.isEmpty()) {
Node cur=q.remove();
System.out.println(cur.key+","+cur.val);
if(cur.left!=null)
q.add(cur.left);
if(cur.right!=null)
q.add(cur.right);
}
}
//查询最小值
public K findMin() {
Node node=root;
while(node.left!=null) {
node=node.left;
}
return node.key;
}
//返回最小值的节点
private Node findMinN(Node cur) {
Node node=cur;
while(node.left!=null) {
node=node.left;
}
return node;
}
//返回最大值
public K findMax() {
Node node=root;
while(node.right!=null) {
node=node.right;
}
return node.key;
}
//删除最小值
public K removeMin() {
K key=findMin();
remove(key);
return key;
}
//删除最大值
public K removeMax() {
K key=findMax();
remove(key);
return key;
}
//删除任意节点
public void remove(K key) {
root=remove(root,key);
}
//返回删除目标节点后的跟节点
private Node remove(Node node,K key) {
if(node==null)
return null;
if(key.compareTo(node.key)<0) {
node.left=remove(node.left, key);
return toBalance(node);
}
else if(key.compareTo(node.key)>0) {
node.right=remove(node.right,key);
return toBalance(node);
}
else {
if(node.right==null) {
Node pre=node.left;
node.left=null;
return pre;
}
if(node.left==null) {
Node pre=node.right;
node.right=null;
return pre;
}
Node pre=findMinN(node.right);
pre.right=remove(node.right,pre.key);
pre.left=node.left;
node.left=node.right=null;
return toBalance(pre);
}
}
//打印AVL树
@Override
public String toString() {
// TODO 自动生成的方法存根
StringBuffer res=new StringBuffer();
generationBSTString(root, 0, res);
return res.toString();
}
private void generationBSTString(Node node,int depth,StringBuffer res) {
if(node==null) {
res.append(generationBSTDepth(depth)+"null\n");
return;
}
res.append(generationBSTDepth(depth)+node.key+"\n");
generationBSTString(node.left, depth+1, res);
generationBSTString(node.right, depth+1, res);
}
private String generationBSTDepth(int depth) {
StringBuffer res=new StringBuffer();
for(int i=0;i<=depth;i++) {
res.append("--");
}
return res.toString();
}
}
一个简单的测试用例:
public class Test {
public static void main(String[] args) {
AVLTree<Integer, Integer> tree=new AVLTree<>();
Random random=new Random();
//添加50以内的随机数,先输出随机数的插入顺序再输出树的结构
for(int i=0;i<10;i++) {
int a=random.nextInt(50);
System.out.print(a+" ");
tree.add(a, -1);
}
System.out.println();
System.out.println(tree);
}
测试用例某一次的输出结果为: