1. 平衡树:带有平衡条件的二叉搜索树,平衡树在每一次结点的插入和删除的时候 对修改的树进行 平衡处理,主要解决二叉搜索树由于某些原因导致树的深度太深退化成链表的形式,保持每一颗树的深度不会超过 log(N)。
AVL平衡树 平衡的条件: 任意结点X的左子树高度与右子树的高度差不能超过1,在BST的基础上,增加一条记录,记录任意的结点的高度。当某一个结点被插入的时候,则结点到根结点的路劲上的结点的平衡性 有肯会被打破,对于这种不平衡的可能性出现在下面的四种情况中:
1). A结点的左儿子的左子树进行一次插入(LL/RR)
2). A结点的左儿子的右子树进行插入(LR/RL)
对于二叉平衡树最重要 在于如何通过旋转操作进行 结点的调整,对于AVL删除操作,采用的策略与BST 一样,寻找删除结点的右子树最小值进行替代,最后在进行调整操作
package com.Tree;
import java.util.LinkedList;
import org.omg.CORBA.Any;
public class AVLTree<AnyType> {
private static class AVLNode<AnyType>{
AnyType element;
AVLNode<AnyType> left;
AVLNode<AnyType>right;
int height;
public AVLNode(AnyType E)
{
this(E,null,null,-1);
}
public AVLNode(AnyType thiselement,AVLNode<AnyType>lt,AVLNode<AnyType>rt,int h)
{
this.element=thiselement;
this.left=lt;
this.right=rt;
this.height=h;
}
}
public AVLNode<AnyType> Avlroot;
public void insert(AnyType x)
{
Avlroot=insert(x,Avlroot);
}
public void remove(AnyType x)
{
Avlroot=remove(x, Avlroot);
}
public AVLNode<AnyType> insert(AnyType x,AVLNode<AnyType> t)
{
if(t==null)
return new AVLNode<AnyType>(x);
/*不是 空树 找到 需要插入的位置*/
int ComparableResult=((Comparable<AnyType>)x).compareTo(t.element);
if(ComparableResult<0)
{
t.left=insert(x, t.left);
}else if(ComparableResult>0)
{
t.right=insert(x, t.right);
}else
{
;
}
/**调整 被插入位置 每插入一个 结点 ,就调整一次 递归特性 从插入点上溯到 根结点 依次进行 树的调整*/
return balance(t);
}
public AVLNode<AnyType> remove(AnyType x,AVLNode<AnyType> t)
{
if(t==null)
return t;
int ComparableResult=((Comparable<AnyType>)x).compareTo(t.element);
if(ComparableResult<0)
{
t.left=remove(x, t.left);
}else if(ComparableResult>0)
{
t.right=remove(x, t.right);
}else if(t.left!=null && t.right!=null) // 定位到被删除的 结点
{
// 删除 同样 BST 一样 采用 右子树 最小值进行替代,最后在进行树的调整
t.element=removeMin(t).element;
System.out.println("删除完毕");
}
else
{
t=(t.left!=null)?t.left:t.right;
}
return balance(t);
}
/**
* 找到最小值点,同时在树中删除此最小值结点
* */
private AVLNode<AnyType> removeMin(AVLNode<AnyType> t) {
AVLNode<AnyType> min=t.right;
System.out.println("要删除值:"+t.element);
AVLNode<AnyType> parent=null;// 两种情况 直线斜树 和 不是斜树
while(min.left!=null)
{
parent=min;// 记录 min 父结点
min=min.left;
}
if(parent==null)
{// 表示 直线斜树
t.right=min.right;//直接删除min结点
}
else
{
parent.left=min.right;
}
return min;
}
public void leveOrder (AVLNode<AnyType> P)
{
//使用层次遍历,使用队列
LinkedList<AVLNode<AnyType>>queue=new LinkedList<AVLNode<AnyType>>();
queue.add(P);
while((P!=null) &&(!queue.isEmpty()))
{
P=queue.element();
System.out.print("["+P.element+"]");
if(P.left!=null) queue.add(P.left);
if(P.right!=null) queue.add(P.right);
queue.remove();
}
}
public static void main(String[] args)
{
int array[]={1,2,3,4,5,6,7,8};
AVLTree<Integer> avlTree=new AVLTree<>();
for(int i=0;i<array.length;i++)
avlTree.insert(array[i]);
avlTree.leveOrder(avlTree.Avlroot);
System.out.println("进行删除操作");
avlTree.remove(6);
avlTree.leveOrder(avlTree.Avlroot);
}
private AVLNode<AnyType> balance(AVLNode<AnyType> t) {
if(t==null)
return t;
if(height(t.left)-height(t.right)>1)
{
/**判断 单旋 还是 双 旋*/
if (height(t.left.left)>= height(t.left.right))
{
t=roateWithLeftChild(t);
}
else
{
t=doubleWithLeftChild(t);
}
}
else
{
if(height(t.right)-height(t.left)>1)
{
if (height(t.right.right)>= height(t.right.left))
{
t=roateWithRightChild(t);
}
else
{
t=doubleWithRightChild(t);
}
}
}
t.height=Math.max(height(t.left),height(t.right))+1;
return t;
}
private AVLNode<AnyType> doubleWithLeftChild(AVLNode<AnyType> k3) {
/* 简化成 两个 单旋转 LR --先 R 在 L**/
k3.left=roateWithRightChild(k3.left);
return roateWithLeftChild(k3);
}
private AVLNode<AnyType> doubleWithRightChild(AVLNode<AnyType> k3) {
/* 简化成 两个 单旋转 RL --先 L 在 R**/
k3.right=roateWithLeftChild(k3.right);
return roateWithRightChild(k3);
}
private AVLNode<AnyType> roateWithLeftChild(AVLNode<AnyType> k2) {
AVLNode<AnyType> k1=k2.left;
k2.left=k1.right;
k1.right=k2;
// 更新 树的高度
k2.height=Math.max(height(k2.left),height(k2.right))+1;
k1.height=Math.max(height(k1.left),k2.height)+1;
return k1;
}
private AVLNode<AnyType> roateWithRightChild(AVLNode<AnyType> k2) {
AVLNode<AnyType> k1=k2.right;
k2.right=k1.left;
k1.left=k2;
// 更新 树的高度
k2.height=Math.max(height(k2.left),height(k2.right))+1;
k1.height=Math.max(height(k1.right),k2.height)+1;
return k1;
}
private int height(AVLNode<AnyType> t) {
return t==null? -1 : t.height;
}
}