平衡二叉树学习(java实现)

破坏平衡的几种情况

 

这是第一种情况,其中A节点和B节点只是平衡二叉树的某一个子集合,要想打破这个平衡,那么插入的节点C必然在B的子节点上,即左右子节点

 

在这里插入图片描述

这是第二种情况,其中A、B、C、D四个节点也是该平衡树的某个子集合,同样要打破这个平衡,那么,插入的节点F必然在D节点上

在这里插入图片描述

第三种情况,其中A、B、C、D、E五个节点也是该平衡树的某个子集合,同样要打破这个平衡,那么,插入的节点F必然在D节点和E节点上。

打破平衡后,经过一系列操作达到平衡,由以上可知,大致有几种情况,可大致分为两大类,如下(以下的A节点就是被打破平衡的那个节点)

第一大类,A节点的左子树高度比右子树高度高2,最终需要经过右旋操作(可能需要先左后右)

第二大类,A节点的左子树高度比右子树高度低2,最终需要经过左旋操作(可能需要先右后左)

代码如下:

package com.demo.tree;

import java.util.LinkedList;
import java.util.Queue;


public class BalancedBinaryTree {

    public static void main(String[] args){
        BalancedBinaryTree tree = new BalancedBinaryTree();
        tree.batchInsert(new int[]{8,6,3,4,5,20,15,23,28,1,2});
        tree.tierPrint();
    }

    private Node root;

    /**
     * 节点
     */
    private class Node{
        int data;   // 数据
        Node left;  // 左指针
        Node right; // 右指针

        private Node(int data) {
            this.data = data;
            this.left = null;
            this.right = null;
        }
    }

    /**
     * 右旋操作(左孩子的左子树插入节点)
     * @param p
     */
    private Node rightRotate(Node p){
        Node temp = p.left;    // temp指向p的左子树
        p.left = temp.right;   // p的左子树指向temp的右子树
        temp.right = p;
        return temp;
    }

    /**
     * 左旋操作(右孩子的右子树插入节点)
     * @param p
     */
    private Node leftRotate(Node p){
        Node temp = p.right;    // temp指向p的右子树
        p.right = temp.left;   // p的右子树指向temp的左子树
        temp.left = p;
        return temp;
    }

    /**
     * 先左旋再右旋(左孩子的右子树插入节点)
     * @param p
     */
    private Node leftRightRotate(Node p){
        p.left = leftRotate(p.left);
        return rightRotate(p);
    }

    /**
     * 先右旋再左旋(右孩子的左子树插入节点)
     * @param p
     */
    private Node rightLeftRotate(Node p){
        p.right = rightRotate(p.right);
        return leftRotate(p);
    }

    /**
     * 树高
     * @param node
     * @return
     */
    private int getDepth(Node node){
        if (node == null){
            return 0;
        }
        return Math.max(getDepth(node.left), getDepth(node.right))+1;
    }

    /**
     * 平衡因子(左高:>1 等高:0 右高:<-1)
     * @return
     */
    public int balanceFactor(Node node){
        if (node == null){
            return 0;
        }
        return getDepth(node.left) - getDepth(node.right);
    }

    /**
     * 插入
     * @param node
     * @param data
     */
    public Node insert(Node node, int data){
        Node newData = new Node(data);
        if (node == null){
            return newData;
        }
        if (data < node.data){
            node.left = insert(node.left, data);
        }else if (data > node.data){
            node.right = insert(node.right, data);
        }else{
            return node;
        }
        int bf = balanceFactor(node);

        if (bf > 1 && data < node.left.data){
            // LL
            System.out.println("LL" + data);
            return rightRotate(node);
        }else if (bf < -1 && data > node.right.data){
            // RR
            System.out.println("RR" + data);
            return leftRotate(node);
        }else if (bf > 1 && data > node.left.data){
            // LR
            System.out.println("LR" + data);
            return leftRightRotate(node);
        }else if (bf < -1 && data < node.right.data){
            // RL
            System.out.println("RL" + data);
            return rightLeftRotate(node);
        }
        return node;
    }

    /**
     * 批量插入
     * @param arr
     */
    public void batchInsert(int[] arr){
        for (int data : arr){
            root = insert(root, data);
        }
    }

    /**
     * 前序遍历
     */
    public void prePrint(){
        System.out.print("前序遍历\t");
        if (root != null){
            pre(root);
        }
        System.out.println();
    }

    private void pre(Node node){
        if (node != null) {
            System.out.print(node.data + "\t");
            pre(node.left);
            pre(node.right);
        }
    }

    /**
     * 中序遍历
     */
    public void midPrint(){
        System.out.print("中序遍历\t");
        if (root != null){
            mid(root);
        }
        System.out.println();
    }

    private void mid(Node node){
        if (node != null) {
            mid(node.left);
            System.out.print(node.data + "\t");
            mid(node.right);
        }
    }

    /**
     * 后序遍历
     */
    public void postPrint(){
        System.out.print("后序遍历\t");
        if (root != null){
            post(root);
        }
        System.out.println();
    }

    private void post(Node node){
        if (node != null) {
            post(node.left);
            post(node.right);
            System.out.print(node.data + "\t");
        }
    }

    /**
     * 层序遍历,利用队列先进先出
     */
    public void tierPrint(){
        if (root != null){
            Queue<Node> queue = new LinkedList<>();
            queue.add(root);
            System.out.print("层序遍历\t");
            while (!queue.isEmpty()){
                Node temp = queue.remove();
                System.out.print(temp.data + "\t");
                if (temp.left != null){
                    // 左节点不为空,放进队列
                    queue.add(temp.left);
                }
                if (temp.right != null){
                    // 右节点不为空,放进队列
                    queue.add(temp.right);
                }
            }
        }
    }

}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值