声明:下面的代码只是一个最基础的实现,没有经过严格的测试
/**
* 平衡二叉树(AVL)
* 1,可以保证查询效率,它是一棵空树或者它的左右两个子树的高度差不超过1,并且左右两个子树都是一颗平衡二叉树。
* 2,实现方式有:红黑树,AVL算法,替罪羊树,Treap,伸展树等。
* 3,平衡二叉树是一种特殊的二叉排序树。除了满足二叉排序树的特性之外,必须在添加新节点时,通过判断左右子树的高度
* 通过左旋转或者右旋转来满足平衡二叉树的特性,即左右两个子树的高度差不能超过1
*/
public class BinaryAVLTree {
public Node root;
public static void main(String[] args) {
BinaryAVLTree tree = new BinaryAVLTree();
int[] arr={10,11,7,6,8,9};
for (int i : arr) {
tree.addNode(i);
}
/* tree.deleteNode(5);
tree.infixOrder();*/
// System.out.println(tree.height(tree.root)); 3
// System.out.println(tree.height(tree.root.left)); 2
// System.out.println(tree.height(tree.root.right)); 2
//System.out.println(tree.root); 8
}
public void addNode(int value){
if(root == null){
root = new Node(value);
}else {
addNode(root,value);
}
}
//递归计算树的高度,每一个节点的高度等于它的子节点高度(左子节点和右子节点取最高的那个) + 1
public int height(Node node){
if(node== null ){
return 0;
}else{
int rightHeight=height(node.right);
int leftHeight=height(node.left);
return Math.max(leftHeight,rightHeight)+1;
}
}
public int rightHeight(Node node){
if(node.right == null){
return 0;
}
return height(node.right);
}
public int leftHeight(Node node){
if(node.left == null){
return 0;
}
return height(node.left);
}
// 对于二叉排序树,中序遍历时输出的值 是 升序排列的
public void infixOrder(){
if(root != null){
infixOrder(root);
}else{
System.out.println("该二叉树为空");
}
}
//中序遍历,先左节点再父节点,后右节点
private void infixOrder(Node node){
if(node==null){
return;
}
//每次都是先输出父节点
if(node.left!=null){
infixOrder(node.left);
}
System.out.println(node);
if(node.right!=null){
infixOrder(node.right);
}
}
/**
* 使用递归的方式新增元素:按照二叉排序树的定义,如果待插入的值比父节点小,则作为左节点。反之则为右节点。
* 值插入的逻辑:先从根节点开始,插入的值和根节点的值比较大小,放到合适的位置。如果根节点有左节点或右节点,那么根节点
* 的左节点或者有节点作为新的父节点,继续和待插入的值比较。直至父节点为null。
* @param parentNode 待插入节点的父节点
* @param value 待插入的值
*/
private void addNode(Node parentNode,int value){
if(parentNode == null){
return;
}
if(value < parentNode.value ){
if(parentNode.left == null){
parentNode.left=new Node(value);
}else{
//如果父节点存在左节点,那么该左节点作为新的父节点进行递归
addNode(parentNode.left,value);
}
}
if(value >= parentNode.value){
if(parentNode.right == null){
parentNode.right=new Node(value);
}else{
//如果父节点存在右节点,那么该右节点作为新的父节点进行递归
addNode(parentNode.right,value);
}
}
Node curNode=parentNode;
//添加完一个节点后,如果右子树高度比左子树高度 大于1
if(rightHeight(curNode) - leftHeight(curNode) > 1){
//如果右子树的左高度大于右子树的右高度
if(curNode.right != null && leftHeight(curNode.right) > rightHeight(curNode.right)){
//先对当前节点的右子树进行右旋转
rightHeight(curNode.right);
//再对当前节点进行左旋转
leftHeight(curNode);
}else{
//直接对当前节点进行左旋转即可
leftHeight(curNode);
}
}
//添加完一个节点后,如果左子树高度比右子树高度 大于1
if(leftHeight(curNode) - rightHeight(curNode) > 1){
//如果左子树的右高度大于左子树的左高度
if(curNode.left != null && rightHeight(curNode.left) > leftHeight(curNode.left)){
//先对当前节点的左子树进行左旋转
leftRotate(curNode.left);
//再对当前节点进行右旋转
rightRotate(curNode);
}else{
//直接对当前节点进行右旋转即可
rightRotate(curNode);
}
}
}
//左旋转。如果左树比右树高,则进行左旋转
private void leftRotate(Node node){
//1,以当前节点的值创建一个新节点
Node newNode = new Node(node.value);
//2,新节点的左子树设置为当前节点的左子树
newNode.left=node.left;
//3,新节点的右子树设置为当前节点右子树的左子树
newNode.right=node.right.left;
//4,当前节点的值替换为右子节点的值
node.value=node.right.value;
//5,当前节点的右子树设置为当前节点右子树的右子树
node.right=node.right.right;
//6,当前节点的左子树(左节点)设置为新节点
node.left=newNode;
}
//右旋转。如果右树比左树高,则进行右旋转
private void rightRotate(Node node){
//1,以当前节点的值创建一个新节点
Node newNode = new Node(node.value);
//2,新节点的右子树设置为当前节点的右子树
newNode.right=node.right;
//3,新节点的左子树设置为当前节点左子树的右子树
newNode.left=node.left.right;
//4,当前节点的值替换为左子节点的值
node.value=node.left.value;
//5,当前节点的左子树设置为当前节点左子树的左子树
node.left=node.left.left;
//6,当前节点的右子树(右节点)设置为新节点
node.right=newNode;
}
class Node{
//value
private Integer value;
//左节点
public Node left;
//右节点
public Node right;
public Node(Integer value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
}
}