/**
* @author LOHAS
* @time 2019-10-4
* @subject ADT AVLTree
* @Main-method:
* 1) Tree Constructor
* 2) Get node's height
* 3) Traverse
* 4) findMax
* 5) findMin
* 6) rotateLLTree
* 7) rotateLRTree
* 8) rotateRLTree
* 9) roatteRRTree
* 10) insert
* 11) remove
* 12) destroy
*/
package tree;
import org.junit.Test;
public class MyAVLTree<T extends Comparable<T>> {
//定义根节点
public AVLNode mroot;
//构造内部类,实现结点的构造函数
class AVLNode<T> {
private T key; //结点的值
private AVLNode left; //左孩子
private AVLNode right; //右孩子
private int height; //结点的高度
public AVLNode(T key) {
this(key, null, null);
}
public AVLNode(T key, AVLNode<T> left, AVLNode<T> right) {
this.key = key;
this.left = left;
this.right = right;
this.height = 0;
}
}
//构造函数
public MyAVLTree2() {
mroot = null;
}
/**
* 获取子树的高度
*
* @param tree
* @return 返回子树高度值
*/
public int height(AVLNode<T> tree) {
if (tree == null)
return 0;
return tree.height;
}
/**
* 获取树的高度
*
* @return
*/
public int height() {
return height(mroot);
}
/**
* 先序遍历
*
* @param node
*/
private void preOrder(AVLNode<T> node) {
if (node != null) {
System.out.print(node.key + "\t");
preOrder(node.left);
preOrder(node.right);
}
}
public void preOrder() {
preOrder(mroot);
}
/**
* 中序遍历
*
* @param node
*/
private void inOrder(AVLNode<T> node) {
if (node != null) {
inOrder(node.left);
System.out.print(node.key + "\t");
inOrder(node.right);
}
}
public void inOrder() {
inOrder(mroot);
}
/**
* 后序遍历
*
* @param node
*/
private void postOrder(AVLNode<T> node) {
if (node != null) {
postOrder(node.left);
postOrder(node.right);
System.out.print(node.key + "\t");
}
}
public void postOrder() {
postOrder(mroot);
}
/**
* 【递归实现】获取AVLTree中最小的结点
*
* @param node
* @return
*/
private AVLNode<T> findMin(AVLNode<T> node) {
if (node == null)
return null;
if (node.left == null)
return node;
return node.left;
}
public AVLNode<T> findMin() {
return findMin(mroot);
}
/**
* 获取AVLTree中最大的结点
*
* @param node
* @return
*/
private AVLNode<T> findMax(AVLNode<T> node) {
if (node == null)
return null;
while (node.right != null) {
node = node.right;
}
return node;
}
public AVLNode<T> findMax() {
return findMin(mroot);
}
/**
* 旋转LL类型的子树(右旋)
*
* @param k2 被破坏平衡树的根结点
* @return 返回平衡后得树
*/
private AVLNode<T> rotateLLTree(AVLNode<T> k2) {
AVLNode<T> k1;
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;
}
/**
* 旋转RR类型的子树(左旋)
*
* @param k2 被破坏平衡后的子树的根结点
* @return 平衡后的子树(根结点)
*/
private AVLNode<T> rotateRRTree(AVLNode<T> k2) {
AVLNode<T> k1;
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;
}
/**
* 旋转LR类型的子树
*
* @param k3
* @return
*/
private AVLNode<T> rotateLRTree(AVLNode<T> k3) {
//先进行RR类型的旋转(左旋)
k3.left = rotateRRTree(k3.left);
//再进行LL类型的旋转(右旋)
return rotateLLTree(k3);
}
/**
* 旋转RL类型的子树
*
* @param k3
* @return
*/
private AVLNode<T> rotateRLTree(AVLNode<T> k3) {
//先进行LL类型的旋转(右旋)
k3.right = rotateLLTree(k3.right);
//再进行RR类型的旋转(左旋)
return rotateRRTree(k3);
}
/**
* 插入结点
*
* @param node
* @param key
* @return
*/
private AVLNode<T> insert(AVLNode<T> node, T key) {
if (node == null) {
node = new AVLNode<T>(key);
} else {
if (key.compareTo(node.key) < 0) {
node.left = insert(node.left, key);
//判断插入结点后是否平衡,若不平衡则需调整
if (height(node.left) - height(node.right) == 2) { //在左子树中插入的
if (key.compareTo((T) node.left.key) < 0) //判断是LL还是LR
node = rotateLLTree(node);
else
node = rotateLRTree(node);
}
} else if (key.compareTo(node.key) > 0) {
node.right = insert(node.right, key);
//判断插入结点后是否平衡,若不平衡则需调整
if (height(node.right) - height(node.left) == 2) { //在右子树中插入的
if (key.compareTo((T) node.right.key) > 0) //判断是RR还是RL
node = rotateRRTree(node);
else
node = rotateRLTree(node);
}
} else {
System.out.println("插入错误:已有相同结点!");
}
}
//计算结点的高度
node.height = Math.max(height(node.left), height(node.right)) + 1;
return node;
}
public void insert(T key) {
mroot = insert(mroot, key);
}
/**
* 删除节点
*
* @param root 根节点
* @param node 被删除的节点
* @return
*/
private AVLNode<T> remove(AVLNode<T> root, AVLNode<T> node) {
if (root == null || node == null) {
return null;
}
int value = node.key.compareTo(root.key);
if (value < 0) {
root.left = remove(root.left, node);
//删除左子树的节点后,右子树可能会比左子树高
if (height(root.right) - height(root.left) == 2) {
AVLNode<T> r = root.right;
//判断是RR还是RL类型
if (height(r.left) < height(r.right)) { //RR类型
root = rotateRRTree(root);
} else //RL类型
root = rotateRLTree(root);
}
} else if (value > 0) {
root.right = remove(root.right, node);
//删除右子树的节点后,左子树可能会比右子树高
if (height(root.left) - height(root.right) == 2) {
AVLNode<T> l = root.left;
if (height(l.left) > height(l.right)) { //LL类型
root = rotateLLTree(root);
} else { //LR类型
root = rotateLRTree(root);
}
}
} else { //找到要删除的结点
//被删除的结点左右子树都不为空的情况
if (root.left != null && root.right != null) {
//若是结点的左子树比右子树高
//则从左子树中选出最大值来替换要被删除的结点
// 把用来替换的结点删除
//这样做的好处是删除节点之后树仍然是平衡的
if (height(root.left) > height(root.right)) {
AVLNode<T> leftMax = findMax(root.left);
root.key = leftMax.key;
root.left = remove(root.left, leftMax);
} else {
//若是右子树比左子树高或相等
//从右子树选出最小的结点来替换要删除的结点
//删除用来替换的结点
//好处是若右子树比左子树高则删除节点之后树仍然是平衡的
AVLNode<T> rightMin = findMin(root.right);
root.key = rightMin.key;
root.right = remove(root.right, rightMin);
}
} else { //被删除结点左右子树非都不为空的情况
root = (root.left == null) ? root.right : root.left;
}
}
return root;
}
public void remove(T key) {
AVLNode<T> node = new AVLNode<>(key);
remove(mroot, node);
}
/**
* 销毁AVLTree
*
* @param node
*/
private void destroy(AVLNode<T> node) {
if (node == null)
return;
if (node.left != null)
destroy(node.left);
if (node.right != null)
destroy(node.right);
node = null; //根节点的处理
}
public void destroy() {
destroy(mroot);
}
/*
* 打印"二叉查找树"
*
* key -- 节点的键值
* direction -- 0,表示该节点是根节点;
* -1,表示该节点是它的父结点的左孩子;
* 1,表示该节点是它的父结点的右孩子。
*/
private void print(AVLNode<T> tree, T key, int direction) {
if (tree != null) {
if (direction == 0) // tree是根节点
System.out.printf("%2d is root\n", tree.key, key);
else // tree是分支节点
System.out.printf("%2d is %2d's %6s child and its height is %2d\n", tree.key, key, direction == 1 ? "right" : "left", tree.height);
print(tree.left, tree.key, -1);
print(tree.right, tree.key, 1);
}
}
public void print() {
if (mroot != null)
print(mroot, (T) mroot.key, 0);
}
//测试代码
@Test
public void MyAVLTreeTest() {
MyAVLTree2<Integer> tree = new MyAVLTree2<Integer>();
int arr[] = {3, 2, 1, 4, 5, 6, 7, 16, 15, 14, 13, 12, 11, 10, 8, 9};
System.out.println("==依次添加==");
for (int i : arr) {
System.out.print(i + "\t");
tree.insert(i);
}
//tree.remove(2);
System.out.println("\n先序遍历");
tree.inOrder();
System.out.println();
tree.print();
System.out.println(tree.height());
}
}
AVL树的实现
最新推荐文章于 2022-10-08 10:25:25 发布