最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java深入分析了解平衡二叉樹(shù)

 更新時(shí)間:2022年06月03日 10:31:15   作者:洛語(yǔ)言  
平衡二叉樹(shù)又被稱為AVL樹(shù)(有別于AVL算法),且具有以下性質(zhì):它是一棵空樹(shù)或它的左右兩個(gè)子樹(shù)的高度差的絕對(duì)值不超過(guò)1,并且左右兩個(gè)子樹(shù)都是一棵平衡二叉樹(shù)。本文將詳解介紹一下平衡二叉樹(shù)的原理與實(shí)現(xiàn),需要的可以參考一下

AVL樹(shù)的引入

搜索二叉樹(shù)有著極高的搜索效率,但是搜索二叉樹(shù)會(huì)出現(xiàn)以下極端情況:

這樣的二叉樹(shù)搜索效率甚至比鏈表還低。在搜索二叉樹(shù)基礎(chǔ)上出現(xiàn)的平衡二叉樹(shù)(AVL樹(shù))就解決了這樣的問(wèn)題。當(dāng)平衡二叉樹(shù)(AVL樹(shù))的某個(gè)節(jié)點(diǎn)左右子樹(shù)高度差的絕對(duì)值大于1時(shí),就會(huì)通過(guò)旋轉(zhuǎn)操作減小它們的高度差。

基本概念

AVL樹(shù)本質(zhì)上還是一棵二叉搜索樹(shù),它的特點(diǎn)是:

  • 本身首先是一棵二叉搜索樹(shù)。
  • 每個(gè)結(jié)點(diǎn)的左右子樹(shù)的高度之差的絕對(duì)值(平衡因子)最多為1。也就是說(shuō),AVL樹(shù),本質(zhì)上是帶了平衡功能的二叉查找樹(shù)(二叉排序樹(shù),二叉搜索樹(shù))。
  • 當(dāng)插入一個(gè)節(jié)點(diǎn)或者刪除一個(gè)節(jié)點(diǎn)時(shí),導(dǎo)致某一個(gè)節(jié)點(diǎn)的左右子樹(shù)高度差的絕對(duì)值大于1,這時(shí)需要通過(guò)左旋和右旋的操作使二叉樹(shù)再次達(dá)到平衡狀態(tài)。

平衡因子(balanceFactor)

  • 一個(gè)結(jié)點(diǎn)的左子樹(shù)與右子樹(shù)的高度之差。
  • AVL樹(shù)中的任意結(jié)點(diǎn)的BF只可能是-1,0和1。

基礎(chǔ)設(shè)計(jì)

下面是AVL樹(shù)需要的簡(jiǎn)單方法和屬性:

public class AVLTree <E extends Comparable<E>>{
    class Node{
        E value;
        Node left;
        Node right;
        int height;
        public Node(){}
        public Node(E value){
            this.value = value;
            height = 1;
            left = null;
            right = null;
        }
        public void display(){
            System.out.print(this.value + " ");
        }
    }
    Node root;
    int size;
    public int size(){
        return size;
    }
    public int getHeight(Node node) {
        if(node == null) return 0;
        return node.height;
    }
    //獲取平衡因子(左右子樹(shù)的高度差,大小為1或者0是平衡的,大小大于1不平衡)
    public int getBalanceFactor(){
        return getBalanceFactor(root);
    }
    public int getBalanceFactor(Node node){
        if(node == null) return 0;
        return getHeight(node.left) - getHeight(node.right);
    }
    //判斷一個(gè)樹(shù)是否是一個(gè)平衡二叉樹(shù)
    public boolean isBalance(Node node){
        if(node == null) return true;
        int balanceFactor = Math.abs(getBalanceFactor(node.left) - getBalanceFactor(node.right));
        if(balanceFactor > 1) return false;
        return isBalance(node.left) && isBalance(node.right);
    }
    public boolean isBalance(){
        return isBalance(root);
    }
    //中序遍歷樹(shù)
    private  void inPrevOrder(Node root){
        if(root == null) return;
        inPrevOrder(root.left);
        root.display();
        inPrevOrder(root.right);
    }
    public void inPrevOrder(){
        System.out.print("中序遍歷:");
        inPrevOrder(root);
    }
}

RR(左旋)

往一個(gè)樹(shù)右子樹(shù)的右子樹(shù)上插入一個(gè)節(jié)點(diǎn),導(dǎo)致二叉樹(shù)變得不在平衡,如下圖,往平衡二叉樹(shù)中插入5,導(dǎo)致這個(gè)樹(shù)變得不再平衡,此時(shí)需要左旋操作,如下:

代碼如下:

//左旋,并且返回新的根節(jié)點(diǎn)
    public Node leftRotate(Node node){
        System.out.println("leftRotate");
       Node cur = node.right;
       node.right = cur.left;
       cur.left = node;
       //跟新node和cur的高度
        node.height = Math.max(getHeight(node.left),getHeight(node.right)) + 1;
        cur.height = Math.max(getHeight(cur.left),getHeight(cur.right)) + 1;
        return cur;
    }

LL(右旋)

往一個(gè)AVL樹(shù)左子樹(shù)的左子樹(shù)上插入一個(gè)節(jié)點(diǎn),導(dǎo)致二叉樹(shù)變得不在平衡,如下圖,往平衡二叉樹(shù)中插入2,導(dǎo)致這個(gè)樹(shù)變得不再平衡,此時(shí)需要左旋操作,如下:

代碼如下:

 //右旋,并且返回新的根節(jié)點(diǎn)
    public Node rightRotate(Node node){
        System.out.println("rightRotate");
        Node cur = node.left;
        node.left = cur.right;
        cur.right = node;
        //跟新node和cur的高度
        node.height = Math.max(getHeight(node.left),getHeight(node.right)) + 1;
        cur.height = Math.max(getHeight(cur.left),getHeight(cur.right)) + 1;
        return cur;
    }

LR(先左旋再右旋)

往AVL樹(shù)左子樹(shù)的右子樹(shù)上插入一個(gè)節(jié)點(diǎn),導(dǎo)致該樹(shù)不再平衡,需要先對(duì)左子樹(shù)進(jìn)行左旋,再對(duì)整棵樹(shù)右旋,如下圖所示,插入節(jié)點(diǎn)為5.

RL(先右旋再左旋)

往AVL樹(shù)右子樹(shù)的左子樹(shù)上插入一個(gè)節(jié)點(diǎn),導(dǎo)致該樹(shù)不再平衡,需要先對(duì)右子樹(shù)進(jìn)行右旋,再對(duì)整棵樹(shù)左旋,如下圖所示,插入節(jié)點(diǎn)為2.

添加節(jié)點(diǎn)

//添加元素
    public  void add(E e){
        root = add(root,e);
    }
    public Node add(Node node, E value) {
        if (node == null) {
            size++;
            return new Node(value);
        }
        if (value.compareTo(node.value) > 0) {
            node.right = add(node.right, value);
        } else if (value.compareTo(node.value) < 0) {
            node.left = add(node.left, value);
        }
        //跟新節(jié)點(diǎn)高度
        node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
        //獲取當(dāng)前節(jié)點(diǎn)的平衡因子
        int balanceFactor = getBalanceFactor(node);
        //該子樹(shù)不平衡且新插入節(jié)點(diǎn)(導(dǎo)致不平衡的節(jié)點(diǎn))在左子樹(shù)的左子樹(shù)上,此時(shí)需要進(jìn)行右旋
        if (balanceFactor > 1 && getBalanceFactor(node.left) >= 0) {
            return rightRotate(node);
        }
        //該子樹(shù)不平衡且新插入節(jié)點(diǎn)(導(dǎo)致不平衡的節(jié)點(diǎn))在右子樹(shù)子樹(shù)的右子樹(shù)上,此時(shí)需要進(jìn)行左旋
        else if (balanceFactor < -1 && getBalanceFactor(node.right) <= 0) {
            return leftRotate(node);
        }
        //該子樹(shù)不平衡且新插入節(jié)點(diǎn)(導(dǎo)致不平衡的節(jié)點(diǎn))在左子樹(shù)的右子樹(shù)上,此時(shí)需要先對(duì)左子樹(shù)左旋,在整個(gè)樹(shù)右旋
        else if (balanceFactor > 1 && getBalanceFactor(node.left) < 0) {
            node.left = leftRotate(node.left);
            return rightRotate(node);
        }
        //balanceFactor < -1 && getBalanceFactor(node.left) > 0
        //該子樹(shù)不平衡且新插入節(jié)點(diǎn)(導(dǎo)致不平衡的節(jié)點(diǎn))在右子樹(shù)的左子樹(shù)上,此時(shí)需要先對(duì)右子樹(shù)右旋,再整個(gè)樹(shù)左旋
        else if(balanceFactor < -1 && getBalanceFactor(node.right) > 0) {
            node.right = rightRotate(node.right);
            return leftRotate(node);
        }
        return node;
    }

刪除節(jié)點(diǎn)

 //刪除節(jié)點(diǎn)
    public E remove(E value){
        root = remove(root,value);
        if(root == null){
            return null;
        }
        return root.value;
    }
    public Node remove(Node node, E value){
        Node retNode = null;
        if(node == null)
            return retNode;
        if(value.compareTo(node.value) > 0){
            node.right = remove(node.right,value);
            retNode = node;
        }
        else if(value.compareTo(node.value) < 0){
            node.left = remove(node.left,value);
            retNode = node;
        }
        //value.compareTo(node.value) = 0
        else{
            //左右節(jié)點(diǎn)都為空,或者左節(jié)點(diǎn)為空
            if(node.left == null){
                size--;
                retNode = node.right;
            }
            //右節(jié)點(diǎn)為空
            else if(node.right == null){
                size--;
                retNode = node.left;
            }
            //左右節(jié)點(diǎn)都不為空
            else{
                Node successor = new Node();
                //尋找右子樹(shù)最小的節(jié)點(diǎn)
                Node cur = node.right;
                while(cur.left != null){
                    cur = cur.left;
                }
                successor.value  = cur.value;
                successor.right = remove(node.right,value);
                successor.left = node.left;
                node.left =  node.right = null;
                retNode = successor;
            }
            if(retNode == null)
                return null;
            //維護(hù)二叉樹(shù)平衡
            //跟新height
            retNode.height = Math.max(getHeight(retNode.left),getHeight(retNode.right));
        }
        int balanceFactor = getBalanceFactor(retNode);
        //該子樹(shù)不平衡且新插入節(jié)點(diǎn)(導(dǎo)致不平衡的節(jié)點(diǎn))在左子樹(shù)的左子樹(shù)上,此時(shí)需要進(jìn)行右旋
        if (balanceFactor > 1 && getBalanceFactor(retNode.left) >= 0) {
            return rightRotate(retNode);
        }
        //該子樹(shù)不平衡且新插入節(jié)點(diǎn)(導(dǎo)致不平衡的節(jié)點(diǎn))在右子樹(shù)子樹(shù)的右子樹(shù)上,此時(shí)需要進(jìn)行左旋
        else if (balanceFactor < -1 && getBalanceFactor(retNode.right) <= 0) {
            return leftRotate(retNode);
        }
        //該子樹(shù)不平衡且新插入節(jié)點(diǎn)(導(dǎo)致不平衡的節(jié)點(diǎn))在左子樹(shù)的右子樹(shù)上,此時(shí)需要先對(duì)左子樹(shù)左旋,在整個(gè)樹(shù)右旋
        else if (balanceFactor > 1 && getBalanceFactor(retNode.left) < 0) {
            retNode.left = leftRotate(retNode.left);
            return rightRotate(retNode);
        }
        //該子樹(shù)不平衡且新插入節(jié)點(diǎn)(導(dǎo)致不平衡的節(jié)點(diǎn))在右子樹(shù)的左子樹(shù)上,此時(shí)需要先對(duì)右子樹(shù)右旋,再整個(gè)樹(shù)左旋
        else if(balanceFactor < -1 && getBalanceFactor(retNode.right) > 0) {
            retNode.right = rightRotate(retNode.right);
            return leftRotate(retNode);
        }
        return  retNode;
    }

到此這篇關(guān)于Java深入分析了解平衡二叉樹(shù)的文章就介紹到這了,更多相關(guān)Java平衡二叉樹(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JDK動(dòng)態(tài)代理接口和接口實(shí)現(xiàn)類(lèi)深入詳解

    JDK動(dòng)態(tài)代理接口和接口實(shí)現(xiàn)類(lèi)深入詳解

    這篇文章主要介紹了JDK動(dòng)態(tài)代理接口和接口實(shí)現(xiàn)類(lèi),JDK動(dòng)態(tài)代理是代理模式的一種實(shí)現(xiàn)方式,因?yàn)樗腔诮涌趤?lái)做代理的,所以也常被稱為接口代理,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • Java報(bào)錯(cuò):UnsupportedOperationException in Collections的解決方案

    Java報(bào)錯(cuò):UnsupportedOperationException in Collection

    在Java編程中,UnsupportedOperationException是一種常見(jiàn)的運(yùn)行時(shí)異常,通常在試圖對(duì)不支持的操作執(zhí)行修改時(shí)發(fā)生,它表示當(dāng)前操作不被支持,本文將深入探討UnsupportedOperationException的產(chǎn)生原因,并提供具體的解決方案和最佳實(shí)踐,需要的朋友可以參考下
    2024-06-06
  • Java常量池詳解

    Java常量池詳解

    下面小編就為大家?guī)?lái)一篇淺談java常量池。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-09-09
  • SpringBoot多數(shù)據(jù)源配置完整指南

    SpringBoot多數(shù)據(jù)源配置完整指南

    在復(fù)雜的企業(yè)應(yīng)用中,經(jīng)常需要連接多個(gè)數(shù)據(jù)庫(kù),Spring Boot 提供了靈活的多數(shù)據(jù)源配置方式,以下是詳細(xì)的實(shí)現(xiàn)方案,需要的朋友可以參考下
    2025-04-04
  • Jersey框架的統(tǒng)一異常處理機(jī)制分析

    Jersey框架的統(tǒng)一異常處理機(jī)制分析

    初學(xué)者往往不清楚java的異常為什么會(huì)設(shè)計(jì)成這個(gè)樣子,他們通常會(huì)對(duì)異常只進(jìn)行簡(jiǎn)單的處理
    2016-07-07
  • JAVA泛型之泛型方法的定義和使用方式

    JAVA泛型之泛型方法的定義和使用方式

    這篇文章主要介紹了JAVA泛型之泛型方法的定義和使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Spring Boot整合Mybatis Plus和Swagger2的教程詳解

    Spring Boot整合Mybatis Plus和Swagger2的教程詳解

    這篇文章主要介紹了Spring Boot整合Mybatis Plus和Swagger2的教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • StringBuffer與StringBuilder底層擴(kuò)容機(jī)制與常用方法

    StringBuffer與StringBuilder底層擴(kuò)容機(jī)制與常用方法

    這篇文章主要給大家介紹了StringBuffer、StringBuilder底層擴(kuò)容機(jī)制與常用方法,有感興趣的小伙伴跟著小編一起來(lái)學(xué)習(xí)吧
    2023-07-07
  • 安裝多個(gè)版本JDK后使用時(shí)的切換方法總結(jié)

    安裝多個(gè)版本JDK后使用時(shí)的切換方法總結(jié)

    我們平時(shí)在window上做開(kāi)發(fā)的時(shí)候,可能需要同時(shí)開(kāi)發(fā)兩個(gè)甚至多個(gè)項(xiàng)目,有時(shí)不同的項(xiàng)目對(duì)JDK的版本要求有區(qū)別,下面這篇文章主要給大家介紹了安裝多個(gè)版本JDK后使用的切換方法,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-01-01
  • springboot省去配置Tomcat的步驟問(wèn)題

    springboot省去配置Tomcat的步驟問(wèn)題

    這篇文章主要介紹了springboot省去配置Tomcat的步驟問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06

最新評(píng)論

凤山县| 忻城县| 和田市| 和平区| 镇安县| 仁化县| 云南省| 那曲县| 江阴市| 曲麻莱县| 元江| 内乡县| 三江| 渭南市| 平阳县| 同心县| 任丘市| 汝城县| 平利县| 陕西省| 荆州市| 彭山县| 涪陵区| 买车| 通榆县| 安福县| 钟祥市| 昌图县| 林州市| 靖边县| 长白| 磐石市| 汾西县| 酉阳| 花莲市| 南皮县| 曲水县| 祁门县| 桂东县| 台中市| 屯留县|