AVLTree.java
package com.lzp;
/**
* Created by Administrator on 2017/6/3 0003.
*/
public class AVLTree<Item extends Comparable<? super Item>> {
private static class Node<Item> {
Node(Item item) {
this.item = item;
this.left = left;
this.right = right;
}
Node(Item item, Node<Item> left, Node<Item> right) {
this.item = item;
this.left = left;
this.right = right;
}
private Item item;
private Node<Item> left;
private Node<Item> right;
private int height;
}
private Node<Item> root;
public AVLTree() {
clear();
}
public void clear() {
root = null;
}
public boolean isEmpty() {
return root == null;
}
public void insert(Item item) {
root = insert(item, root);
}
private Node<Item> insert(Item item, Node<Item> node) {
if(node == null)
return new Node(item, null, null);
int compareResult = item.compareTo(node.item);
if(compareResult < 0)
node.left = insert(item, node.left);
else if(compareResult > 0)
node.right = insert(item, node.right);
else
;
return balance(node); // 平衡树
}
private Node<Item> balance(Node<Item> node) {
if(node == null)
return node;
if(height(node.left) - height(node.right) > ALLOWED_IMBALANCE){
// A A
// / /
// B B
// / \
// C C
if(height(node.left.left) >= height(node.left.right))
node = rotateWithLeftChild(node);
else
node = doubleWithLeftChild(node);
} else if(height(node.right) - height(node.left) > ALLOWED_IMBALANCE){
// A A
// \ \
// B B
// / \
// C C
if(height(node.right.right) >= height(node.right.left))
node = rotateWithRightChild(node);
else
node = doubleWithRightChild(node);
}
node.height = Math.max(height(node.left), height(node.right)) + 1;
return node;
}
// 左左模型
// k2 k1
// / \
// k1 k2
// k2 是要旋转的节点
private Node<Item> rotateWithLeftChild(Node<Item> k2) {
Node<Item> 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;
}
// 右右模型
// k1 k2
// \ /
// k2 k1
// k1 是要旋转的节点
private Node<Item> rotateWithRightChild(Node<Item> k1) {
Node<Item> k2 = k1.right;
k1.right = k2.left;
k2.left = k1;
k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
k2.height = Math.max(height(k2.right), k1.height) + 1;
return k2;
}
// 左右模型 -- 首先进行儿子k1和孙子k2的右旋转,再进行k3与k2的左旋转
// k3 k3
// / /
// k1 --> k2 --> k2
// \ / / \
// k2 k1 k1 k3
private Node<Item> doubleWithLeftChild(Node<Item> k3) {
k3.left = rotateWithRightChild(k3.left);
return rotateWithLeftChild(k3);
}
// 右左模型 -- 首先进行右儿子k3和孙子k2的左旋转,再进行k1与k2的右旋转
// k1 k1
// \ \
// k3 --> k2 --> k2
// / \ / \
// k2 k3 k1 k3
private Node<Item> doubleWithRightChild(Node<Item> k1) {
k1.right = rotateWithLeftChild(k1.right);
return rotateWithRightChild(k1);
}
public void remove(Item item) {
root = remove(item, root);
}
private Node<Item> remove(Item item, Node<Item> node) {
if(node == null)
return node;
int compareResult = item.compareTo(node.item);
if(compareResult < 0)
node.left = remove(item, node.left);
else if(compareResult > 0)
node.right = remove(item, node.right);
else if(node.left != null && node.right != null){
node.item = findMin(node.right).item;
node.right = remove(node.item, node.right);
} else {
node = (node.left != null) ? node.left : node.right;
}
// 正常的二叉树删除 + 再平衡
return balance(node);
}
// AVL平衡树
// 每个节点的左子树和右子树的高度最多差 1
private static final int ALLOWED_IMBALANCE = 1;
// 检查是否是平衡树
public void checkBlance(){
checkBlance(root);
}
private int checkBlance(Node<Item> node) {
if(node == null)
return -1;
if(node != null){
int hl = checkBlance(node.left); // 返回左右枝高度
int hr = checkBlance(node.right);
if(Math.abs(height(node.left) - height(node.right)) > 1 // 相邻枝高度差大于1
|| height(node.left) != hl
|| height(node.right) != hr)
System.out.println("不平衡");
}
return height(node);
}
private int height(Node<Item> node){
return node == null ? -1 : node.height;
}
// 最大最小值
public Item findMin() {
if (isEmpty())
throw new RuntimeException("tree is empty");
return findMin(root).item;
}
private Node<Item> findMin(Node<Item> node) {
if (node == null)
return node;
while (node.left != null)
node = node.left;
return node;
}
public Item findMax() {
if (isEmpty())
throw new RuntimeException("tree is empty");
return findMax(root).item;
}
private Node<Item> findMax(Node<Item> node) {
if(node == null)
return node;
else if(node.right == null)
return node;
return findMax(node.right);
}
public boolean contains(Item item){
return contains(item, root);
}
private boolean contains(Item item, Node<Item> node) {
while(node != null){
int compareResult = item.compareTo(node.item);
if(compareResult < 0)
node = node.left;
else if(compareResult > 0)
node = node.right;
else
return true;
}
return false;
}
public void printTree(){
if(isEmpty())
System.out.println("tree is empty");
else
printTree(root);
}
private void printTree(Node<Item> node) {
if(node != null){
printTree(node.left);
System.out.println(node.item);
printTree(node.right);
}
}
}