AVL樹是一種自平衡的二叉查找樹。首先它是一種二叉查找樹,滿足任意一個節點(葉子節點除外)的值大於它左子樹上任意一個節點,且小於它右子樹上任意一個節點。因爲二叉查找樹的深度可能爲O(N),這樣的效率較低,因此衍生出了AVL樹,它具有自平衡的效果,能保持樹的深度爲O(logN)。AVL樹滿足:任意一個節點它的左子樹的高度和右子樹的高度差不超過1。(假設葉子節點的高度爲0,null節點的高度爲-1)
基於上述的理論完成程序的編寫,既然要保存每個節點的高度,Node節點就需要一個int類型的height變量。自己完成的是採用遞歸的方法,以後有時間完成非遞歸方法的實現。上代碼:
public class TreeTest
{
public static void main(String[] args)
{
AVLTree<Integer> st=new AVLTree<Integer>();
st.insert(15);
st.insert(7);
st.insert(5);
st.insert(37);
st.insert(70);
System.out.println("插入節點:"+st);
st.remove(7);
st.remove(15);
System.out.println("刪除節點:"+st);
}
}
//AVL樹:每個節點的左子樹和右子樹的高度差最多爲1
class AVLTree<T extends Comparable<T>>
{
private Node<T> root=null;
public AVLTree()
{
}
public void insert(T t)
{
root=insert(t,root);
}
public void remove(T t)
{
root=remove(t,root);
}
public T findMax()
{
if(root==null) //如果還沒有元素則返回空
return null;
return findMax(root).element;
}
public T findMin()
{
if(root==null) //如果還沒有元素則返回空
return null;
return findMin(root).element;
}
//先序遍歷
public void printFirst()
{
System.out.print("先序遍歷:");
printFirst(root);
System.out.print("\n");
}
private void printFirst(Node<T> node)
{
if(node!=null)
{
System.out.print(node.element+" ");
printFirst(node.left);
printFirst(node.right);
}
}
//中序遍歷
public void printTree()
{
System.out.print("中序遍歷:");
printTree(root);
System.out.print("\n");
}
private void printTree(Node<T> node)
{
if(node!=null)
{
printTree(node.left);
System.out.print(node.element+" ");
printTree(node.right);
}
}
//插入分爲4總情況,分爲兩組,這兩組鏡像對稱。返回之前要進行node的高度賦值
private Node<T> insert(T t,Node<T> node)
{
if(node==null)
return new Node<T>(t,null,null);
int i=t.compareTo(node.element);
if(i>0)
{
node.right=insert(t,node.right);
int cha=height(node.left)-height(node.right);
if(cha>1 | cha<-1)
{
if(t.compareTo(node.right.element)>0)
node=singleRightChild(node);
else
node=doubleRightChild(node);
}
}
else
{
if(i<0)
{
node.left=insert(t,node.left);
int cha=height(node.left)-height(node.right);
if(cha>1 | cha<-1)
{
if(t.compareTo(node.left.element)<0)
node=singleLeftChild(node);
else
node=doubleLeftChild(node);
}
}
}
node.height=Math.max(height(node.left),height(node.right))+1;
return node;
}
//刪除節點方法:遞歸刪除(三種情況),再判斷node節點左右子節點的高度差,|差|>1則進行旋轉平衡,高度賦值
private Node<T> remove(T t,Node<T> node)
{
if(node==null)
return null;
int i=t.compareTo(node.element);
if(i==0)
{
if(node.right!=null && node.left!=null)
{
node.element=findMin(node.right).element;
node.right=remove(node.element,node.right);
}
else
node=(node.right==null)?node.left:node.right;
}
else if(i>0)
node.right=remove(t,node.right);
else
node.left=remove(t,node.left);
if(node!=null) //如果該節點不爲空,則進行平衡的判別處理和高度的賦值
{
if(height(node.right)-height(node.left)>1) //進行右旋轉
{
if(height(node.right.right)>=height(node.right.left)) //進行單旋轉
node=singleRightChild(node);
else //進行雙旋轉
node=doubleRightChild(node);
}
else if(height(node.left)-height(node.right)>1) //進行左旋轉
{
if(height(node.left.left)>=height(node.left.right)) //進行單旋轉
node=singleLeftChild(node);
else //進行雙旋轉
node=doubleLeftChild(node);
}
node.height=Math.max(height(node.right),height(node.left))+1;
}
return node;
}
private Node<T> singleRightChild(Node<T> node)
{
Node<T> n=node.right;
node.right=n.left;
n.left=node;
node.height=Math.max(height(node.left),height(node.right))+1;
n.height=Math.max(height(n.right),height(n.left))+1;
return n;
}
private Node<T> singleLeftChild(Node<T> node)
{
Node<T> n=node.left;
node.left=n.right;
n.right=node;
node.height=Math.max(height(node.left),height(node.right))+1;
n.height=Math.max(height(n.right),height(n.left))+1;
return n;
}
//一次雙旋轉=兩次單旋轉
private Node<T> doubleRightChild(Node<T> node)
{
node.right=singleLeftChild(node.right);
return singleRightChild(node);
}
private Node<T> doubleLeftChild(Node<T> node)
{
node.left=singleRightChild(node.left);
return singleLeftChild(node);
}
//返回節點的高度,空節點爲-1。新建節點的高度爲0
private int height(Node<T> node)
{
return (node==null)?-1:node.height;
}
//返回元素最小的節點
private Node<T> findMin(Node<T> node)
{
if(node==null)
return null;
if(node.left==null)
return node;
return findMin(node.left);
}
//返回元素最大的節點
private Node<T> findMax(Node<T> node)
{
if(node==null)
return null;
if(node.right==null)
return node;
return findMax(node.right);
}
//節點類,包含元素和高度信息
private static class Node<T>
{
private T element;
private int height;
private Node<T> left;
private Node<T> right;
public Node(T element,Node<T> left,Node<T> right)
{
this.element=element;
this.left=left;
this.right=right;
height=0;
}
}
@Override
public String toString()
{
StringBuilder sb=new StringBuilder();
sb.append("[");
sb.append(print(root));
sb.append("]");
return sb.toString();
}
//遞歸輸出,中序遍歷
private String print(Node<T> node)
{
if(node!=null)
{
StringBuilder sb=new StringBuilder();
sb.append(print(node.left));
if(node.left!=null)
sb.append(",");
sb.append(node.element);
if(node.right!=null)
sb.append(",");
sb.append(print(node.right));
return sb.toString();
}
return "";
}
}
輸出結果: