
平衡二叉树是二叉排序树或二叉搜索树的优化
旋转是为了平衡
左旋转:

右旋转:
package tree;
//平衡二叉树,是二叉排序树的优化
public class AvlTreeDemo {
public static void main(String[] args) {
int[] arr = {4,3,6,5,7,8};
// int[] arr = {10,7,6,8,9,11};
AvlTree avlTree = new AvlTree();
for(int i=0;i<arr.length;i++) {
avlTree.add(new Node1(arr[i]));
}
//中序遍历
System.out.println("中序遍历");
avlTree.infixOrder();
System.out.println("树的高度= "+avlTree.getRoot().height());
System.out.println("树的左子树的高度= "+avlTree.getRoot().leftHeight());
System.out.println("树的右子树的高度= "+avlTree.getRoot().rightHeight());
}
}
class AvlTree{
private Node1 root;
//返回头节点
public Node1 getRoot() {
return root;
}
//定义添加方法
public void add(Node1 Node1) {
if(root == null) {
root = Node1;
}else {
root.add(Node1);
}
}
//中序遍历方法
public void infixOrder() {
if(root != null) {
root.infixOrder();
}else {
System.out.println("二叉排序树为空");
}
}
}
//定义节点
class Node1{
int val;
Node1 left;
Node1 right;
public Node1(int val) {
this.val = val;
}
@Override
public String toString() {
return "Node1 [val=" + val + "]";
}
//添加节点方法,递归添加
public void add(Node1 Node1) {
if(Node1 == null) {
return;
}
//判断传入的值,和当前子树根节点值的关系
if(Node1.val < this.val) {
//如果当前节点左子节点为null
if(this.left == null) {
this.left = Node1;
}else {
//递归向左子树添加
this.left.add(Node1);
}
}else {//与上面相反
if(this.right == null) {
this.right = Node1;
}else {
this.right.add(Node1);
}
}
//当一个节点添加完后,判断如何旋转最后平衡
//(右子树高度 - 左子树高度 > 1) 左旋转
if(rightHeight() - leftHeight() > 1) {//总体进行左旋转但是需要满足以下条件
//如果它的右子树的左子树高度大于它的右子树的右子树的高度
if(right != null && right.rightHeight() > right.leftHeight()) {
//先进行当前节点的右子树进行右旋转
right.rightRotate();
//再对当前节点左旋转
leftRotate();
}else {
//直接左旋转
leftRotate();
}
return;//这个return的作用是这两个判断高度差的if条件只走一个
}
//(左子树高度 - 右子树高度 > 1) 右旋转
if(leftHeight() - rightHeight() > 1) {
if(left != null && left.rightHeight() > left.leftHeight()) {
left.leftRotate();
rightRotate();
}else {
rightRotate();
}
}
}
//中序遍历方法
public void infixOrder() {
if(this.left != null) {
this.left.infixOrder();
}
System.out.println(this);
if(this.right != null) {
this.right.infixOrder();
}
}
//在判断旋转之前先要有返回高度的方法
//返回当前节点的高度
public int height() {
return Math.max(left == null ? 0:left.height(),
right == null?0 : right.height()) + 1; //每一层加1
}
//返回当前节点的左子树的高度
public int leftHeight() {
if(left == null) {
return 0;
}
return left.height();
}
//返回当前节点的右子树的高度
public int rightHeight() {
if(right == null) {
return 0;
}
return right.height();
}
//左旋转方法
private void leftRotate() {
//创建新的节点,附上当前节点的值
Node1 newNode1 = new Node1(val);
//把新节点的左子树设置为当前节点的左子树
newNode1.left = left;
//把新节点的右子树设置为当前节点的右子树的左子树
newNode1.right = right.left;
//把当前节点的值改为当前节点的右节点的值
val = right.val;
//把当前节点的右子树设置为当前节点的右子树的右子树
right = right.right;
//把当前节点的左子树设置为新节点
left = newNode1;
}
//右旋转方法与左旋转方法完全相反
private void rightRotate() {
Node1 newNode1 = new Node1(val);
newNode1.right = right;
newNode1.left = left.right;
val = left.val;
left = left.left;
right = newNode1;
}
}
1062

被折叠的 条评论
为什么被折叠?



