二叉平衡树
1、概念
是一颗空树或者左右两个子树的高度差不超过 1,且左右子树本身也都是一颗平衡二叉树
2、将一棵普通的二叉树变为一棵平衡二叉树
/*
当一棵树的右子树的高度减去左子树的高度大于 1的时候
使用左旋转来将二叉树变为平衡二叉树
步骤:
1、创建一个新的节点 newNode,这个新节点的值等于当前根节点的值
2、把新节点的左子节点指向根节点的左子节点
3、把新节点的右子节点指向为根节点的右子节点的左子节点
4、把根节点的值替换为根节点的右子节点的值
5、把根节点的右子节点指向根节点的右子节点的右子节点
6、把根节点的左子节点指向下新节点
当一棵树的左子树的高度减去右子树的高度大于 1的时候
使用右旋转来将二叉树变为平衡二叉树
步骤:
1、创建一个新的节点 newNode,这个新节点的值等于当前根节点的值
2、把新节点的右子节点指向根节点的右子节点
3、把新节点的左子节点指向为根节点的左子节点的右子节点
4、把根节点的值替换为根节点的左子节点的值
5、把根节点的左子节点指向根节点的左子节点的左子节点
6、把根节点的右子节点指向下新节点
注意:
1、当符合右旋转,但是它的左子节点的右子树高度大于它的左子节点的左子树高度时
1.1、先对根节点的左节点进行左旋转
1.2、在对根节点进行右旋转即可
2、当符合左旋转,但是它的右子节点的左子树高度大于它的右子节点的右子树高度时
2.1、先对根节点的右节点进行右旋转
2.2、在对根节点进行左旋转即可
*/
//左旋转
//返回以该节点为根节点的高度
public int height() {
return Math.max(left == null ? 0 : left.height(), right == null ? 0 : right.height()) + 1;
}
//返回左子树的高度
public int leftHeight() {
if (left == null) {
return 0;
}
return left.height();
}
//左旋转二叉树
public void leftRotate() {
Nodes newNodes = new Nodes(this.getValue());
newNodes.setLeft(this.getLeft());
newNodes.setRight(this.getRight().getLeft());
this.setValue(this.getRight().getValue());
this.setRight(this.getRight().getRight());
this.setLeft(newNodes);
}
//右旋转
//返回以该节点为根节点的高度
public int height() {
return Math.max(left == null ? 0 : left.height(), right == null ? 0 : right.height()) + 1;
}
//返回右子树的高度
public int rightHeight() {
if (right == null) {
return 0;
}
return right.height();
}
//右旋转二叉树
public void rightRotate() {
Nodes newNodes = new Nodes(this.getValue());
newNodes.setRight(this.getRight());
newNodes.setLeft(this.getLeft().getRight());
this.setValue(this.getLeft().getValue());
this.setLeft(this.getLeft().getLeft());
this.setRight(newNodes);
}
/**
* 添加节点
*
* @param node 需要添加的值
*/
public void add(Nodes node) {
if (node == null) {
return;
}
//判断传入的节点与当前节点的关系来决定如何插入
if (node.getValue() < this.value) {
//如果当前节点的左节点为空
if (this.getLeft() == null) {
this.setLeft(node);
} else {
this.getLeft().add(node);
}
} else {
//如果当前节点的右节点为空
if (this.getRight() == null) {
this.setRight(node);
} else {
this.getRight().add(node);
}
}
//当添加完一个元素之后,判断右子树高度减去左子树高度是否大于1,如果大于,则左旋转
if (this.rightHeight() - this.leftHeight() > 1) {
//如果它的左子树的右子树高度大于它的左子树的左子树高度
if (this.getRight() != null && this.getRight().leftHeight() > this.getRight().rightHeight()) {
//先对当前节点进行左旋转
this.getRight().rightRotate();
//在对当前节点进行右旋转
leftRotate();
} else {
leftRotate();
}
return;
}
//当添加完一个元素之后,判断左子树高度减去右子树高度是否大于1,如果大于,则右旋转
if (this.leftHeight() - this.rightHeight() > 1) {
//如果它的左子树的右子树高度大于它的左子树的左子树高度
if (this.getLeft() != null && this.getLeft().rightHeight() > this.getLeft().leftHeight()) {
//先对当前节点进行左旋转
this.getLeft().leftRotate();
//在对当前节点进行右旋转
rightRotate();
} else {
rightRotate();
}
}
}
3、完整的代码
public class AVLTreeDemo {
public static void main(String[] args) {
int[] array = {10, 11, 7, 6, 8, 9};
AVLTree avlTree = new AVLTree();
for (int i = 0; i < array.length; i++) {
avlTree.add(new Nodes(array[i]));
}
//遍历
System.out.print("中序遍历:");
avlTree.middleOrder();
System.out.println();
System.out.println("树的高度:" + avlTree.getRoot().height());
System.out.println("树的左子树的高度:" + avlTree.getRoot().leftHeight());
System.out.println("树的右子树的高度:" + avlTree.getRoot().rightHeight());
}
}
//AVL树
class AVLTree {
private Nodes root;
public Nodes getRoot() {
return root;
}
//添加节点的办法
public void add(Nodes nodes) {
if (root == null) {
root = nodes;
} else {
root.add(nodes);
}
}
//中序遍历
public void middleOrder() {
if (root != null) {
root.middleOrder();
} else {
System.out.println("二叉排序树为空,不能遍历!");
}
}
}
//节点类
class Nodes {
private int value;
private Nodes left;
private Nodes right;
public Nodes(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Nodes getLeft() {
return left;
}
public void setLeft(Nodes left) {
this.left = left;
}
public Nodes getRight() {
return right;
}
public void setRight(Nodes right) {
this.right = right;
}
//返回左子树的高度
public int leftHeight() {
if (left == null) {
return 0;
}
return left.height();
}
//返回右子树的高度
public int rightHeight() {
if (right == null) {
return 0;
}
return right.height();
}
//返回以该节点为根节点的高度
public int height() {
return Math.max(left == null ? 0 : left.height(), right == null ? 0 : right.height()) + 1;
}
//左旋转二叉树
public void leftRotate() {
Nodes newNodes = new Nodes(this.getValue());
newNodes.setLeft(this.getLeft());
newNodes.setRight(this.getRight().getLeft());
this.setValue(this.getRight().getValue());
this.setRight(this.getRight().getRight());
this.setLeft(newNodes);
}
//右旋转二叉树
public void rightRotate() {
Nodes newNodes = new Nodes(this.getValue());
newNodes.setRight(this.getRight());
newNodes.setLeft(this.getLeft().getRight());
this.setValue(this.getLeft().getValue());
this.setLeft(this.getLeft().getLeft());
this.setRight(newNodes);
}
/**
* 添加节点
*
* @param node 需要添加的值
*/
public void add(Nodes node) {
if (node == null) {
return;
}
//判断传入的节点与当前节点的关系来决定如何插入
if (node.getValue() < this.value) {
//如果当前节点的左节点为空
if (this.getLeft() == null) {
this.setLeft(node);
} else {
this.getLeft().add(node);
}
} else {
//如果当前节点的右节点为空
if (this.getRight() == null) {
this.setRight(node);
} else {
this.getRight().add(node);
}
}
//当添加完一个元素之后,判断右子树高度减去左子树高度是否大于1,如果大于,则左旋转
if (this.rightHeight() - this.leftHeight() > 1) {
//如果它的左子树的右子树高度大于它的左子树的左子树高度
if (this.getRight() != null && this.getRight().leftHeight() > this.getRight().rightHeight()) {
//先对当前节点进行左旋转
this.getRight().rightRotate();
//在对当前节点进行右旋转
leftRotate();
} else {
leftRotate();
}
return;
}
//当添加完一个元素之后,判断左子树高度减去右子树高度是否大于1,如果大于,则右旋转
if (this.leftHeight() - this.rightHeight() > 1) {
//如果它的左子树的右子树高度大于它的左子树的左子树高度
if (this.getLeft() != null && this.getLeft().rightHeight() > this.getLeft().leftHeight()) {
//先对当前节点进行左旋转
this.getLeft().leftRotate();
//在对当前节点进行右旋转
rightRotate();
} else {
rightRotate();
}
}
}
//中序遍历
public void middleOrder() {
if (this.left != null) {
this.left.middleOrder();
}
System.out.print(this.getValue() + "->");
if (this.right != null) {
this.right.middleOrder();
}
}
}