[AVL balanced binary tree] JAVA code implementation

Keywords: Java data structure Binary tree

Realization idea

AVL balanced binary tree adds the balancing function on the basis of binary search tree, that is, after inserting data according to the rules of balanced binary tree, it is still necessary to ensure that the depth difference between the left and right subtrees of any node does not exceed 1, so as to ensure the query efficiency of binary tree to the greatest extent

Binary lookup tree

The idea of binary search tree is very simple, that is, the data is inserted from the root node. If the insertion value is greater than the node, the data is inserted as the left child node of the node (less than, the right child node). If the left child node (right child node) already exists, the value is passed to the left child node (right child node) for repeated comparison until an empty insertion is found.
If a sorted array is inserted into the binary search tree, it is very easy to form chain storage, resulting in the invalidation of the query advantage of the binary tree itself

Implementation of binary search tree

Firstly, the binary lookup tree follows the insertion mode of small right and large left

    public void add(Point p){//Usually inserted from the root node
        if(p.info<this.getInfo()){//If the value of the node to be inserted is less than the current node value
            if(this.getLeftPoint()!=null){//If the left child node of the current node already exists
                this.getLeftPoint().add(p);//Compare the left child node of the node to be inserted to the current node again
            }else{
                this.setLeftPoint(p);//If the current node has no left child node, the node completes the insertion as the left child node of the current node
            }
        }
        if(p.info>this.getInfo()){
            if(this.getRightPoint()!=null){
                this.getRightPoint().add(p);
            }else{
                this.setRightPoint(p);
            }
        }
        //balance();// This method is the balance method of balanced binary tree
    }

Balanced binary tree implementation

Balanced binary tree adds rotation method on the basis of binary search tree, so as to ensure that the depth difference between each sub tree of binary tree will not be greater than 2

Rotation method

The rotation method is divided into left rotation and right rotation. If the left subtree depth of the current node is greater than 2 or more than the right subtree depth, it will rotate to the right, and vice versa

    //Rotate left
    private void leftRotate() {
        /**
         * When the right node has only one left subtree, the relationship between the left node and its right subtree needs to be adjusted first
         * Set the right child node of the left child node as the left node, and set the original left child node as the left child node of the new left child node
         * Convenient rotation
         */
        Point newPoint;
        if(this.getRightPoint().getLeftPoint()!=null && this.getRightPoint().getRightPoint()==null){
            newPoint = this.getRightPoint();
            this.setRightPoint(this.getRightPoint().getLeftPoint());
            this.getRightPoint().setRightPoint(newPoint);
            this.getRightPoint().getRightPoint().setLeftPoint(null);
        }
        newPoint = new Point(this.info);
        if(this.getLeftPoint()!=null){
            newPoint.setLeftPoint(this.getLeftPoint());
        }
        this.setLeftPoint(newPoint);
        this.setInfo(this.getRightPoint().getInfo());
        /**
         * When both the left and right child nodes of the right node exist, set the left node of the right node as the right subtree of the left node and the right subtree of the right node as the right subtree of the root node
         */
        if(this.getRightPoint().getLeftPoint()!=null){
            this.getLeftPoint().setRightPoint(this.getRightPoint().getLeftPoint());
        }
        this.setRightPoint(this.getRightPoint().getRightPoint());

    }
    //Rotate right
    private void rightRotate() {
        /**
         * When the left node has only one right subtree point, the relationship between the left node and its right subtree needs to be adjusted first
         */
        Point newPoint;
        if(this.getLeftPoint().getRightPoint()!=null && this.getLeftPoint().getLeftPoint()==null){
            newPoint = this.getLeftPoint();
            this.setLeftPoint(this.getLeftPoint().getRightPoint());
            this.getLeftPoint().setLeftPoint(newPoint);
            this.getLeftPoint().getLeftPoint().setRightPoint(null);
        }

        newPoint = new Point(this.info);
        if(this.getRightPoint()!=null){
            newPoint.setRightPoint(this.getRightPoint());
        }
        this.setRightPoint(newPoint);
        this.setInfo(this.getLeftPoint().getInfo());
        /**
         * When both the left and right child nodes of the left node exist, the right node of the left node is set as the left child tree of the right node, and the left child tree of the left node is set as the left child tree of the root node
         */
        if(this.getLeftPoint().getRightPoint()!=null){
            this.getRightPoint().setLeftPoint(this.getLeftPoint().getRightPoint());
        }
        this.setLeftPoint(this.getLeftPoint().getLeftPoint());
    }

Use of rotation method

After the balanced binary tree completes operations that may change the depth of the tree, such as insertion and deletion, it is necessary to call the balanced method

Complete code

Binary tree class

The method to get the root node is reconstructed, because the root node may change after calling rotation

package AVLTree;

import java.util.ArrayList;
import java.util.List;

public class Tree {

    private Point rootPoint;

    public List<Point> getPointsList() {
        return pointsList;
    }

    public void setPointsList(List<Point> pointsList) {
        this.pointsList = pointsList;
    }

    private List<Point> pointsList = new ArrayList<Point>();

    public Point getRootPoint() {
        List<Point> list = new ArrayList<Point>();
        for(Point p : pointsList){
            list.add(p);
        }
        for(Point p:pointsList){
            for(int i = 0;i<list.size();i++){
                if(p.getLeftPoint()!=null){
                    if(p.getLeftPoint().getInfo()==list.get(i).getInfo()){
                        list.remove(i);
                    }
                }
                if(p.getRightPoint()!=null){
                    if(p.getRightPoint().getInfo()==list.get(i).getInfo()){
                        list.remove(i);
                    }
                }
            }
        }
        return list.get(0);
    }

    public void setRootPoint(Point rootPoint) {
        this.rootPoint = rootPoint;
    }



    Tree(int[] arr){
        int midNum = getMidNum(arr);
        this.rootPoint = new Point(midNum);
        this.pointsList.add(this.rootPoint);
        for(int i:arr){
            if(i!=this.rootPoint.getInfo()){
                Point p = new Point(i);
                this.getRootPoint().add(p);
                this.pointsList.add(p);
            }
        }
    }

    /**
     * Medium order traversal
     * @param p
     */
    void showTre(Point p){
        if (p.getLeftPoint() != null) {
            showTre(p.getLeftPoint());
        }
        System.out.println(p.getInfo());
        if(p.getRightPoint()!=null){
            showTre(p.getRightPoint());
        }
    }

    int getMidNum(int[] arr){
        int x=0;
        for(int i=0;i<arr.length;i++){
            for(int j=0;j< arr.length;j++){
                if(arr[i]<arr[j]){
                    x = arr[i];
                    arr[i] =arr[j];
                    arr[j] = x;
                }
            }
        }
        return arr[arr.length/2];
    }

}

Node class

package AVLTree;

public class Point {
    private int info;
    private int deep=0;
    private Point leftPoint;

    public int getInfo() {
        return info;
    }

    public void setInfo(int info) {
        this.info = info;
    }

    public Point getLeftPoint() {
        return leftPoint;
    }

    public void setLeftPoint(Point leftPoint) {
        this.leftPoint = leftPoint;
    }

    public Point getRightPoint() {
        return rightPoint;
    }

    public void setRightPoint(Point rightPoint) {
        this.rightPoint = rightPoint;
    }

    private Point rightPoint;

    Point(int info){
        this.info = info;
    }


    public int getDeep() {
        return deep;
    }

    public void setDeep(){
        this.deep = getHight();
    }

    public int getLeftHight(){
        if(this.getLeftPoint()==null){
            return 0;
        }
        return this.getLeftPoint().getHight();
    }
    public int getRightHight(){
        if(this.getRightPoint()==null){
            return 0;
        }
        return this.getRightPoint().getHight();
    }

    public int getHight(){
        if(this.getRightPoint()==null && this.getLeftPoint()==null){
            return 1;
        }else{
            return Math.max(this.getLeftPoint() == null ? 0 : this.getLeftPoint().getHight(), this.getRightPoint() == null ? 0 : this.getRightPoint().getHight())+ 1;
        }
    }

    public void add(Point p){
        if(p.info<this.getInfo()){
            if(this.getLeftPoint()!=null){
                this.getLeftPoint().add(p);
            }else{
                this.setLeftPoint(p);
            }
        }
        if(p.info>this.getInfo()){
            if(this.getRightPoint()!=null){
                this.getRightPoint().add(p);
            }else{
                this.setRightPoint(p);
            }
        }
        //balance();
    }
    //Rotate left
    private void leftRotate() {
        /**
         * When the right node has only one left subtree, the relationship between the left node and its right subtree needs to be adjusted first
         * Set the right child node of the left child node as the left node, and set the original left child node as the left child node of the new left child node
         * Convenient rotation
         */
        Point newPoint;
        if(this.getRightPoint().getLeftPoint()!=null && this.getRightPoint().getRightPoint()==null){
            newPoint = this.getRightPoint();
            this.setRightPoint(this.getRightPoint().getLeftPoint());
            this.getRightPoint().setRightPoint(newPoint);
            this.getRightPoint().getRightPoint().setLeftPoint(null);
        }
        newPoint = new Point(this.info);
        if(this.getLeftPoint()!=null){
            newPoint.setLeftPoint(this.getLeftPoint());
        }
        this.setLeftPoint(newPoint);
        this.setInfo(this.getRightPoint().getInfo());
        /**
         * When both the left and right child nodes of the right node exist, set the left node of the right node as the right subtree of the left node and the right subtree of the right node as the right subtree of the root node
         */
        if(this.getRightPoint().getLeftPoint()!=null){
            this.getLeftPoint().setRightPoint(this.getRightPoint().getLeftPoint());
        }
        this.setRightPoint(this.getRightPoint().getRightPoint());

    }
    //Rotate right
    private void rightRotate() {
        /**
         * When the left node has only one right subtree point, the relationship between the left node and its right subtree needs to be adjusted first
         */
        Point newPoint;
        if(this.getLeftPoint().getRightPoint()!=null && this.getLeftPoint().getLeftPoint()==null){
            newPoint = this.getLeftPoint();
            this.setLeftPoint(this.getLeftPoint().getRightPoint());
            this.getLeftPoint().setLeftPoint(newPoint);
            this.getLeftPoint().getLeftPoint().setRightPoint(null);
        }

        newPoint = new Point(this.info);
        if(this.getRightPoint()!=null){
            newPoint.setRightPoint(this.getRightPoint());
        }
        this.setRightPoint(newPoint);
        this.setInfo(this.getLeftPoint().getInfo());
        /**
         * When both the left and right child nodes of the left node exist, the right node of the left node is set as the left child tree of the right node, and the left child tree of the left node is set as the left child tree of the root node
         */
        if(this.getLeftPoint().getRightPoint()!=null){
            this.getRightPoint().setLeftPoint(this.getLeftPoint().getRightPoint());
        }
        this.setLeftPoint(this.getLeftPoint().getLeftPoint());
    }
    void balance(){

        //If the left subtree is longer than the right subtree, rotate it to the right
        if(this.getLeftHight()-this.getRightHight()>1){
            this.rightRotate();
            return;
        }
        //If the right subtree is longer than the left subtree, rotate it to the left
        if(this.getRightHight()-this.getLeftHight()>1){
            this.leftRotate();
            return;
        }
    }

}

Test class

package AVLTree;

public class TestMain {


    public static void main(String[] args){
        int[] arr = {34,5,12,32,67,87};
        Tree tree = new Tree(arr);
        tree.showTre(tree.getRootPoint());
    }

}

Posted by bugsuperstar37 on Mon, 22 Nov 2021 22:32:12 -0800