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

Java數(shù)據(jù)結(jié)構(gòu)之二叉搜索樹(shù)詳解

 更新時(shí)間:2022年06月06日 08:30:16   作者:Carol淋  
二叉搜索樹(shù)作為一個(gè)經(jīng)典的數(shù)據(jù)結(jié)構(gòu),具有鏈表的快速插入與刪除的特點(diǎn),同時(shí)查詢(xún)效率也很優(yōu)秀,所以應(yīng)用十分廣泛。本文將詳細(xì)講講二叉搜索樹(shù)的原理與實(shí)現(xiàn),需要的可以參考一下

前言

今天leetcode的每日一題450是關(guān)于刪除二叉搜索樹(shù)節(jié)點(diǎn)的,題目要求刪除指定值的節(jié)點(diǎn),并且需要保證二叉搜索樹(shù)性質(zhì)不變,做完之后,我覺(jué)得這道題將二叉搜索樹(shù)特性凸顯的很好,首先需要查找指定節(jié)點(diǎn),然后刪除節(jié)點(diǎn)并且保持二叉搜索樹(shù)性質(zhì)不變,就想利用這個(gè)題目講講二叉搜索樹(shù)。

二叉搜索樹(shù)作為一個(gè)經(jīng)典的數(shù)據(jù)結(jié)構(gòu),具有鏈表的快速插入與刪除的特點(diǎn),同時(shí)查詢(xún)效率也很優(yōu)秀,所以應(yīng)用十分廣泛,例如在文件系統(tǒng)和數(shù)據(jù)庫(kù)系統(tǒng)一般會(huì)采用這種數(shù)據(jù)結(jié)構(gòu)進(jìn)行高效率的排序與檢索操作。同時(shí)因?yàn)閷?shí)現(xiàn)也簡(jiǎn)單,作為一些公司算法題入門(mén)題目也是常有的事情,所以很需要被掌握哦~

所有源碼已經(jīng)放在我的github中,其中包括之前實(shí)現(xiàn)算法及每日一題,可以查看Data-Structures-and-Algorithms哦~

性質(zhì)

二叉搜索樹(shù)或者是一棵空樹(shù),或者是具有下列性質(zhì)的一棵二叉樹(shù),如果當(dāng)前節(jié)點(diǎn)具有左子樹(shù),則左子樹(shù)上的每一個(gè)節(jié)點(diǎn)值均小于等于當(dāng)前節(jié)點(diǎn)值,如果當(dāng)前節(jié)點(diǎn)具有右子樹(shù),則右子樹(shù)上的每一個(gè)節(jié)點(diǎn)值均大于等于當(dāng)前節(jié)點(diǎn)值。依據(jù)這個(gè)性質(zhì),當(dāng)我們前序遍歷二叉搜索樹(shù)的時(shí)候,得到的序列應(yīng)該是從小到大的非遞減序列。同時(shí)搜索指定值時(shí),只需要與當(dāng)前節(jié)點(diǎn)比較,根據(jù)相對(duì)大小在左子樹(shù)或者右子樹(shù)上進(jìn)行搜索。

實(shí)現(xiàn)

根據(jù)二叉搜索樹(shù)的性質(zhì)我們接下來(lái)需要實(shí)現(xiàn)插入節(jié)點(diǎn),查詢(xún)節(jié)點(diǎn),刪除節(jié)點(diǎn)功能。

節(jié)點(diǎn)結(jié)構(gòu)

public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode() {
    }

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

初始化

這里我們假設(shè)所有節(jié)點(diǎn)值大于0,初始化一個(gè)頭節(jié)點(diǎn)。ps:對(duì)于樹(shù),鏈表這類(lèi)數(shù)據(jù)結(jié)構(gòu),為了使第一個(gè)節(jié)點(diǎn)操作與其他節(jié)點(diǎn)保持一致,方便操作,常見(jiàn)的方法是添加一個(gè)額外的頭節(jié)點(diǎn),指向第一個(gè)節(jié)點(diǎn)。

TreeNode head;
    private void init() {
        //添加一個(gè)頭節(jié)點(diǎn)
        head = new TreeNode(-1);
    }

插入節(jié)點(diǎn)

從頭節(jié)點(diǎn)開(kāi)始我們遍歷二叉搜索樹(shù),如果當(dāng)前節(jié)點(diǎn)值小于等于插入節(jié)點(diǎn)值,則插入節(jié)點(diǎn)在當(dāng)前節(jié)點(diǎn)的右子樹(shù)上,否則在左子樹(shù)上,一直深度遍歷知道當(dāng)前節(jié)點(diǎn)的右子樹(shù)(左子樹(shù))為空,則插入。

/**
     * 插入新節(jié)點(diǎn),假設(shè)新節(jié)點(diǎn)均大于0
     * @param val 插入節(jié)點(diǎn)值
     * @return 插入的節(jié)點(diǎn)
     */
    public TreeNode insert(int val) {
        TreeNode temp = head;
        while (true) {
            if (temp.val < val) {
                //val應(yīng)該在右子樹(shù)上
                if (null != temp.right) {
                    temp = temp.right;
                    continue;
                } else {
                    temp.right = new TreeNode(val);
                    return temp.right;
                }
            }
            //應(yīng)該在左子樹(shù)上
            if (null != temp.left) {
                temp = temp.left;
                continue;
            }
            temp.left = new TreeNode(val);
            return temp.left;
        }
    }

查找節(jié)點(diǎn)

查找節(jié)點(diǎn)的步驟其實(shí)在插入節(jié)點(diǎn)的時(shí)候已經(jīng)有體現(xiàn),其實(shí)就是將查找值與當(dāng)前節(jié)點(diǎn)比較,大于當(dāng)前節(jié)點(diǎn)走右子樹(shù),小于當(dāng)前節(jié)點(diǎn)走左子樹(shù),直到值匹配返回節(jié)點(diǎn),或者沒(méi)有找到返回null。ps:這里為了后面方便實(shí)現(xiàn)刪除,同時(shí)返回了當(dāng)前節(jié)點(diǎn)以及當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn),這里使用了commons-lang3包下的Pair工具。

/**
     * 搜索節(jié)點(diǎn)值
     * @param val
     * @return
     */
    public Pair<TreeNode, TreeNode> find(int val) {
        TreeNode temp = head.right;
        TreeNode parent = head;
        while (null != temp) {
            if (temp.val == val) {
                return Pair.of(temp, parent);
            }
            parent = temp;
            if (temp.val < val) {
                //在右子樹(shù)上
                temp = temp.right;
                continue;
            }
            temp = temp.left;
        }
        return null;
    }

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

刪除節(jié)點(diǎn)時(shí)候我們需要先找到刪除節(jié)點(diǎn)的位置,然后做對(duì)應(yīng)操作。有三種情況:

1.如果刪除的是葉子節(jié)點(diǎn)直接刪除

2.如果刪除的節(jié)點(diǎn)只有左子樹(shù)或者右子樹(shù),則直接將左子樹(shù)或者右子樹(shù)節(jié)點(diǎn)放在刪除節(jié)點(diǎn)位置

3.如果刪除節(jié)點(diǎn)同時(shí)有左子樹(shù)和右子樹(shù),則將右子樹(shù)節(jié)點(diǎn)放在原來(lái)節(jié)點(diǎn)位置,將左子樹(shù)放在右子樹(shù)最左邊節(jié)點(diǎn)左子樹(shù)上(反之將左子樹(shù)放在原來(lái)節(jié)點(diǎn)位置,右子樹(shù)放在左子樹(shù)最右邊節(jié)點(diǎn)右子樹(shù)上也可)

/**
     * 1.如果刪除的是葉子節(jié)點(diǎn)直接刪除,
     * 2.如果刪除的節(jié)點(diǎn)只有左子樹(shù)或者右子樹(shù),則直接將左子樹(shù)或者右子樹(shù)節(jié)點(diǎn)放在刪除節(jié)點(diǎn)位置
     * 3.如果刪除節(jié)點(diǎn)同時(shí)右左子樹(shù)和右子樹(shù),則將右子樹(shù)節(jié)點(diǎn)放在原來(lái)節(jié)點(diǎn)位置,將左子樹(shù)放在右子樹(shù)最左邊節(jié)點(diǎn)左子樹(shù)上
     * @param val
     */
    public void delete(int val) {
        //找到刪除節(jié)點(diǎn),刪除節(jié)點(diǎn)父節(jié)點(diǎn)
        Pair<TreeNode, TreeNode> curAndParent = this.find(val);
        TreeNode cur = curAndParent.getLeft();
        TreeNode parent = curAndParent.getRight();
        //記錄刪除當(dāng)前節(jié)點(diǎn)后,當(dāng)前節(jié)點(diǎn)位置放置哪個(gè)節(jié)點(diǎn)
        TreeNode changed;
        if (null == cur.left && null == cur.right) {
            changed = null;
        } else if (null != cur.left && null != cur.right) {
            TreeNode tempRight = cur.right;
            while (null != tempRight.left) {
                //找到最左側(cè)節(jié)點(diǎn)
                tempRight = tempRight.left;
            }
            tempRight.left = cur.left;
            changed = cur.right;
        } else if (null != cur.left) {
            changed = cur.left;
        } else {
            changed = cur.right;
        }
        if (parent.left == cur) {
            parent.left = changed;
            return;
        }
        parent.right = changed;
    }

最后

二叉搜索樹(shù)易于實(shí)現(xiàn),思想簡(jiǎn)單,被廣泛應(yīng)用,平均查找,插入,刪除時(shí)間均為O(logn),但是在刪除或者插入節(jié)點(diǎn)的過(guò)程中,可能因?yàn)閿?shù)據(jù)的特點(diǎn),使得二叉搜索樹(shù)極端情況下退化為一棵僅有左子樹(shù)或者右子樹(shù)的,這時(shí)候就跟普通順序查找無(wú)異,時(shí)間復(fù)雜度變?yōu)镺(n),因此后面出現(xiàn)了平衡二叉搜索樹(shù),左右子樹(shù)高度相差不超過(guò)1,通過(guò)旋轉(zhuǎn)將二叉樹(shù)高度降低,使得查找、插入、刪除在平均和最壞情況下都是O(logn)。比如常見(jiàn)的AVL自平衡二叉搜索樹(shù),紅黑樹(shù)等等。

到此這篇關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之二叉搜索樹(shù)詳解的文章就介紹到這了,更多相關(guān)Java二叉搜索樹(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java反射機(jī)制詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java反射機(jī)制詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了Java反射機(jī)制的相關(guān)資料,主要包括反射的概念、作用
    2017-06-06
  • 基于Tomcat7、Java、WebSocket的服務(wù)器推送聊天室實(shí)例

    基于Tomcat7、Java、WebSocket的服務(wù)器推送聊天室實(shí)例

    HTML5 WebSocket實(shí)現(xiàn)了服務(wù)器與瀏覽器的雙向通訊,本篇文章主要介紹了基于Tomcat7、Java、WebSocket的服務(wù)器推送聊天室實(shí)例,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2016-12-12
  • Java反射機(jī)制詳解

    Java反射機(jī)制詳解

    這篇文章主要介紹了Java反射機(jī)制,首先簡(jiǎn)單介紹了反射機(jī)制的預(yù)備知識(shí),進(jìn)一步分析了Java反射機(jī)制的原理、實(shí)現(xiàn)技巧與應(yīng)用方法,需要的朋友可以參考下
    2015-12-12
  • 詳解Java LinkedHashMap與HashMap的使用

    詳解Java LinkedHashMap與HashMap的使用

    這篇文章主要通過(guò)幾個(gè)示例為大家詳細(xì)介紹了Java中LinkedHashMap與HashMap的常見(jiàn)使用和概述,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-10-10
  • spring cloud consul注冊(cè)的服務(wù)報(bào)錯(cuò)critical的解決

    spring cloud consul注冊(cè)的服務(wù)報(bào)錯(cuò)critical的解決

    這篇文章主要介紹了spring cloud consul注冊(cè)的服務(wù)報(bào)錯(cuò)critical的解決,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-03-03
  • Java后端傳時(shí)間戳給前端的三種方式

    Java后端傳時(shí)間戳給前端的三種方式

    時(shí)間戳是一份能夠表示一份數(shù)據(jù)在一個(gè)特定時(shí)間點(diǎn)已經(jīng)存在的完整的可驗(yàn)證的數(shù)據(jù),本文給大家介紹了Java后端傳時(shí)間戳給前端的三種方式,并通過(guò)代碼示例講解的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2024-12-12
  • Java的異常處理體系詳解

    Java的異常處理體系詳解

    這篇文章主要介紹了Java的異常處理體系,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java中多態(tài)的實(shí)現(xiàn)原理詳細(xì)解析

    Java中多態(tài)的實(shí)現(xiàn)原理詳細(xì)解析

    這篇文章主要介紹了Java中多態(tài)的實(shí)現(xiàn)原理詳細(xì)解析,多態(tài)是面向?qū)ο缶幊陶Z(yǔ)言的重要特性,它允許基類(lèi)的指針或引用指向派生類(lèi)的對(duì)象,而在具體訪問(wèn)時(shí)實(shí)現(xiàn)方法的動(dòng)態(tài)綁定,需要的朋友可以參考下
    2024-01-01
  • Java?Stream流的常見(jiàn)生成和操作方法總結(jié)

    Java?Stream流的常見(jiàn)生成和操作方法總結(jié)

    從Java1.8開(kāi)始提出了Stream流的概念,本文將通過(guò)示例為大家詳細(xì)講解一下Stream流的常見(jiàn)生成和操作方法,感興趣的小伙伴可以了解一下
    2022-09-09
  • Maven中resources標(biāo)簽的用法詳解

    Maven中resources標(biāo)簽的用法詳解

    本文主要介紹了Maven中resources標(biāo)簽的用法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評(píng)論

永泰县| 台江县| 双流县| 赤壁市| 乐安县| 会东县| 陇南市| 宝山区| 休宁县| 武强县| 蚌埠市| 阿图什市| 崇州市| 鹤壁市| 高清| 房产| 田东县| 陈巴尔虎旗| 伊金霍洛旗| 文登市| 甘德县| 抚远县| 天柱县| 正安县| 闸北区| 肥东县| 峨眉山市| 商河县| 拉孜县| 额济纳旗| 辽宁省| 丰宁| 如皋市| 安泽县| 洪洞县| 永德县| 拉萨市| 三明市| 韩城市| 平阳县| 莱芜市|