java資料結構和演算法——平衡二叉樹之左旋轉

小志的部落格發表於2020-10-13

1、平衡二叉樹左旋轉思路圖解

在這裡插入圖片描述

2、什麼時候進行平衡二叉樹左旋轉

  • 當右子樹與左子樹高度差的絕對值大於1是進行左旋轉

3、平衡二叉樹左旋轉目的

  • 降低右子樹高度

4、求二叉樹高度程式碼示例

1)、建立一個節點類 Node

package com.rf.springboot01.dataStructure.avlTree;

/**
 * @description: 建立一個節點類 Node
 * @author: xiaozhi
 * @create: 2020-10-13 22:04
 */
public class Node {
    public int value;//節點的值
    public Node left;//左節點
    public Node right;//右節點

    //構造方法
    public Node(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }
    /** 
    * @Description:  返回以當前節點為根節點的樹的高度
    * @Author: xz
    * @Date: 2020/10/13 22:07
    */
    public int height(){
        return  Math.max(left ==null ? 0 : left.height(),right == null ? 0 : right.height())+1;
    }
    /** 
    * @Description: 返回左子樹的高度
    * @Author: xz
    * @Date: 2020/10/13 22:10
    */
    public int leftHeight(){
        if(left == null){
            return 0;
        }
        return  left.height();
    }
    /**
    * @Description: 返回右子樹的高度
    * @Author: xz
    * @Date: 2020/10/13 22:11
    */
    public int rightHeight(){
        if(right ==null){
            return 0;
        }
        return right.height();
    }
    /**
     * @Description: 一、遞迴的形式新增結點,注意需要滿足二叉排序樹的要求
     * @Param:  node 傳入的幾點
     * @Author: xz
     * @Date: 2020/9/27 21:58
     */
    public void addNode(Node node){
        if(node == null){
            return;
        }
        if(node.value < this.value){//新增的結點的值 < 當前結點的值
            if(this.left == null){ //如果當前結點左子結點為null
                this.left = node;
            }else{//遞迴的向左子樹新增
                this.left.addNode(node);
            }
        }else{//新增的結點的值 > 當前結點的值
            if(this.right == null){ //如果當前結點右子結點為null
                this.right = node;
            }else{//遞迴的向右子樹新增
                this.right.addNode(node);
            }
        }
    }

    /**
     * @Description: 二、中序遍歷二叉排序樹
     * @Param:
     * @Author: xz
     * @return:
     * @Date: 2020/9/27 22:09
     */
    public void infixOrder(){
        //左子節點不為null,向左子節點中序遍歷
        if(this.left != null){
            this.left.infixOrder();
        }

        //輸出當前節點
        System.out.println(this);

        //右子節點不為null,向右子節點中序遍歷
        if(this.right != null) {
            this.right.infixOrder();
        }
    }

}

2)、建立平衡二叉樹類(即AVL樹類)

package com.rf.springboot01.dataStructure.avlTree;

/**
 * @description: 建立平衡二叉樹(即AVL樹)
 * @author: xiaozhi
 * @create: 2020-10-13 22:13
 */
public class AVLTree {
    public Node root;

    public Node getRoot() {
        return root;
    }

    /**
     * @Description:  一、新增二叉排序樹節點方法
     * @Param:  node 傳入的節點
     * @Author: xz
     * @Date: 2020/9/27 22:18
     */
    public void addBstNode(Node node){
        if(root == null){//如果root為空則直接讓root指向node
            root = node;
        }else{
            root.addNode(node);
        }
    }
    /**
     * @Description:  二、中序遍歷二叉排序樹方法
     * @Param:
     * @Author: xz
     * @return:
     * @Date: 2020/9/27 22:25
     */
    public void infixOrder() {
        if(root != null) {
            root.infixOrder();
        } else {
            System.out.println("二叉排序樹為空,不能遍歷");
        }
    }

}

3)、建立二叉樹測試類

package com.rf.springboot01.dataStructure.avlTree;

/**
 * @description: 平衡二叉樹測試類
 * @author: xiaozhi
 * @create: 2020-10-13 22:15
 */
public class AVLTreeTest {
    public static void main(String[] args) {
        //定義一個陣列
        int[] arr={4,3,6,5,7,8};
        //建立一個AVL樹物件
        AVLTree avlTree = new AVLTree();
        //新增節點
        for(int i=0;i<arr.length;i++){
            avlTree.addBstNode(new Node(arr[i]));
        }
        //中序遍歷
        System.out.println("中序遍歷二叉樹==============");
        avlTree.infixOrder();

        System.out.println("沒有進行平衡處理前============");
        System.out.println("樹的高度:"+avlTree.getRoot().height());
        System.out.println("左子樹的高度:"+avlTree.getRoot().leftHeight());
        System.out.println("右子樹的高度:"+avlTree.getRoot().rightHeight());
    }
}

4)、執行main函式,輸出結果如下:

在這裡插入圖片描述

5、平衡二叉樹左旋轉程式碼示例(基於求二叉樹高度的基礎上新增左旋轉方法程式碼)

1)、建立一個節點類 Node

package com.rf.springboot01.dataStructure.avlTree;

/**
 * @description: 建立一個節點類 Node
 * @author: xiaozhi
 * @create: 2020-10-13 22:04
 */
public class Node {
    public int value;//節點的值
    public Node left;//左節點
    public Node right;//右節點

    //構造方法
    public Node(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }
    /** 
    * @Description:  返回以當前節點為根節點的樹的高度
    * @Author: xz
    * @Date: 2020/10/13 22:07
    */
    public int height(){
        return  Math.max(left ==null ? 0 : left.height(),right == null ? 0 : right.height())+1;
    }
    /** 
    * @Description: 返回左子樹的高度
    * @Author: xz
    * @Date: 2020/10/13 22:10
    */
    public int leftHeight(){
        if(left == null){
            return 0;
        }
        return  left.height();
    }
    /**
    * @Description: 返回右子樹的高度
    * @Author: xz
    * @Date: 2020/10/13 22:11
    */
    public int rightHeight(){
        if(right ==null){
            return 0;
        }
        return right.height();
    }
    /**
    * @Description:  左旋轉方法
    * @Author: xz
    * @Date: 2020/10/13 22:44
    */
    public void leftRotate() {
        //建立新的結點,以當前根結點的值
        Node newNode = new Node(value);
        //把新的結點的左子樹設定成當前結點的左子樹
        newNode.left = left;
        //把新的結點的右子樹設定成帶你過去結點的右子樹的左子樹
        newNode.right = right.left;
        //把當前結點的值替換成右子結點的值
        value = right.value;
        //把當前結點的右子樹設定成當前結點右子樹的右子樹
        right = right.right;
        //把當前結點的左子樹(左子結點)設定成新的結點
        left = newNode;
    }

    /**
     * @Description: 一、遞迴的形式新增結點,注意需要滿足二叉排序樹的要求
     * @Param:  node 傳入的幾點
     * @Author: xz
     * @Date: 2020/9/27 21:58
     */
    public void addNode(Node node){
        if(node == null){
            return;
        }
        if(node.value < this.value){//新增的結點的值 < 當前結點的值
            if(this.left == null){ //如果當前結點左子結點為null
                this.left = node;
            }else{//遞迴的向左子樹新增
                this.left.addNode(node);
            }
        }else{//新增的結點的值 > 當前結點的值
            if(this.right == null){ //如果當前結點右子結點為null
                this.right = node;
            }else{//遞迴的向右子樹新增
                this.right.addNode(node);
            }
        }

        //當新增完一個結點後,如果: (右子樹的高度-左子樹的高度) > 1 , 左旋轉
        if(rightHeight() - leftHeight() > 1) {
                leftRotate();
        }
    }

    /**
     * @Description: 二、中序遍歷二叉排序樹
     * @Param:
     * @Author: xz
     * @return:
     * @Date: 2020/9/27 22:09
     */
    public void infixOrder(){
        //左子節點不為null,向左子節點中序遍歷
        if(this.left != null){
            this.left.infixOrder();
        }

        //輸出當前節點
        System.out.println(this);

        //右子節點不為null,向右子節點中序遍歷
        if(this.right != null) {
            this.right.infixOrder();
        }
    }

}

2)、建立平衡二叉樹類(即AVL樹)

package com.rf.springboot01.dataStructure.avlTree;

/**
 * @description: 建立平衡二叉樹(即AVL樹)
 * @author: xiaozhi
 * @create: 2020-10-13 22:13
 */
public class AVLTree {
    public Node root;

    public Node getRoot() {
        return root;
    }

    /**
     * @Description:  一、新增二叉排序樹節點方法
     * @Param:  node 傳入的節點
     * @Author: xz
     * @Date: 2020/9/27 22:18
     */
    public void addBstNode(Node node){
        if(root == null){//如果root為空則直接讓root指向node
            root = node;
        }else{
            root.addNode(node);
        }
    }
    /**
     * @Description:  二、中序遍歷二叉排序樹方法
     * @Param:
     * @Author: xz
     * @return:
     * @Date: 2020/9/27 22:25
     */
    public void infixOrder() {
        if(root != null) {
            root.infixOrder();
        } else {
            System.out.println("二叉排序樹為空,不能遍歷");
        }
    }

}

3)、建立平衡二叉樹測試類

package com.rf.springboot01.dataStructure.avlTree;

/**
 * @description: 平衡二叉樹測試類
 * @author: xiaozhi
 * @create: 2020-10-13 22:15
 */
public class AVLTreeTest {
    public static void main(String[] args) {
        //定義一個陣列
        int[] arr={4,3,6,5,7,8};
        //建立一個AVL樹物件
        AVLTree avlTree = new AVLTree();
        //新增節點
        for(int i=0;i<arr.length;i++){
            avlTree.addBstNode(new Node(arr[i]));
        }
        //中序遍歷
        System.out.println("中序遍歷二叉樹==============");
        avlTree.infixOrder();

        System.out.println("平衡二叉樹進行左旋轉處理後============");
        System.out.println("樹的高度:"+avlTree.getRoot().height());
        System.out.println("左子樹的高度:"+avlTree.getRoot().leftHeight());
        System.out.println("右子樹的高度:"+avlTree.getRoot().rightHeight());
    }
}

4)、執行main函式,輸出結果如下:

在這裡插入圖片描述

相關文章