《java數據結構》--一篇解決二叉搜索樹!!

😸二叉搜索樹的概念

二叉搜索樹又名二叉排序樹,一般具有以下性質:

  1. 若它的左子樹不為空,則左子樹上所有節點的值都小于根節點的值
  2. 若它的右子樹不為空,則右子樹上所有節點的值都大于根節點的值
  3. 它的左右子樹也分別為二叉搜索樹

將其具現為一個圖就是這樣?

🐭二叉搜索樹的查找

我們可以根據二叉搜索樹的特性,它的每一個結點的左子樹比根小右子樹比根大來進行快速查找,當一個數比根結點小就往根結點的左邊找,比根結點大就往右邊找,每次都可以將搜索范圍縮小一半,最多查找h(樹的高度)次,一個相對平衡的二叉樹搜索樹的時間復雜度大概為O(logN),為什么要說相對平衡呢?🤔因為在極端情況下,假如一棵二叉樹只有右子樹,那么他就會變成一個鏈表,這時他的復雜度就會變成O(logN)。所以在實際使用中,要注意維護二叉搜索樹的平衡性(形狀),因此在二叉搜索樹的基礎上,就誕生出了一些更具平衡性的樹如,紅黑樹,AVL樹。

🐭二叉搜索樹的排序

因為二叉搜索樹的每一棵子樹都滿足左子樹 < 根 < 右子樹,所以我們可以進行中序遍歷,這樣就可以得到一個升序序列了,一個相對平衡的二叉樹搜索樹的時間復雜度大概為O(NlogN)

😸二叉搜索樹的實現

🐱二叉搜索樹的創建

具體方法和創建一棵二叉樹一樣,每棵樹都要有左右子樹,然后創建一個初始的根結點

🐱二叉搜索樹的查找

為了方便我們先寫一個判空方法😋

🐭思路:

  1. 從根節點開始一直向下遍歷
  2. 當目標值大于當前結點的值,就往右子樹中繼續搜索
  3. 當目標值小于當前結點的值,就往左子樹中繼續搜索
  4. 當目標值剛好等于當前結點值,直接返回true表示已經找到
  5. 當遍歷到最后依然每找到則返回false表示沒找到

這里我來畫圖舉個例子:

🐱二叉搜索樹的插入

🐭思路:

二叉搜索樹的插入只能插到葉子結點上,而且不能插入相同的結點

首先需要先判斷樹是否為空

樹為空:

😊即根結點為空,直接插入就行

樹不為空:

😊因為二叉樹不像鏈表,直接遍歷到最后一個結點然后將新結點連在最后一個結點的后就行,二叉搜索樹可能要插在左邊還可能插在右邊,所以不能像鏈表那樣直接cur.next != null找到最后一個結點,我們要先定義一個父節點,用來標記要插到的葉子結點的父節點,先找到這個父節點然后在判斷,要插入的值和這個父節點的大小以判斷是插在左邊還是右邊。

🐱🐱二叉搜素樹的刪除(難點)

🐭思路:

首先我們要先找到要刪除的結點,并且還有記住他的父節點,方法和剛剛寫的插入類似,大的往右找小的往左找,當找到后對結點進行刪除,那么要怎么刪除呢🧐?因為比較復雜,需要單獨寫一個方法😋。

//parent是待刪除的結點的父結點,cur是要刪除的結點

因為這是一個二叉樹刪除之后不能破壞它的結構所以不能像線性表那樣直接刪除,要分幾種情況:

🐭要刪除的結點左邊為空cur.left==null

1.cur是根結點,則直接讓root = cur.right

要刪除的結點左邊為空,并且是根結點所以直接讓根結點等于其右子樹就行

2. cur 不是 root,cur 是 parent.left,則 parent.left = cur.right

如圖,因為要刪除的結點沒有左子樹,并且是父節點的左子樹,所以直接讓父節點的左邊連上cur的右邊

3. cur 不是 root,cur 是 parent.right,則 parent.right = cur.right

和上一個類似,因為要刪除的結點沒有左子樹,并且是父節點的右子樹,所以直接讓父節點的右邊連上cur的右邊

🐭要刪除的結點右邊為空cur.right == null

1. cur 是 root,則 root = cur.left

因為要刪除的結點右邊為空,并且是根結點所以直接讓根結點等于根結點的左子樹

2. cur 不是 root,cur 是 parent.left,則 parent.left = cur.left

因為cur是父節點的左邊,并且cur沒有右子樹,所以直接讓父節點的左邊,連cur的左邊

3. cur 不是 root,cur 是 parent.right,則 parent.right = cur.left

因為cur是父節點的右邊,并且沒有右子樹,所以直接讓父節點的右邊連cur的左邊

🐭要刪除的結點左右都為空cur.left != null && cur.right != null

這種情況利用上面的方法依然可以實現,比如cur在父節點的右邊,因為cur沒有子樹,所以不管父節點連cur的左邊還是右邊(左右都為null)都可以完成刪除,cue在父節點左邊也是一樣的,所以這部分內容利用上面的代碼也能實現

以上我們討論的是要刪除的結點右空的子樹的情況,那么接下來我們要討論沒有子樹的情況即

🐭要刪除的結點左右都不為空

當cur左右結點都不為空時就會比較麻煩,我們的老招式就不管用了😣😟比如這樣:

這該讓父節點怎么連?🤔好像不管怎么連都會破壞樹的結構🧐那么索性就不連了,因為當樹的結構比較復雜時這樣很容易就會破壞樹的結構,那么就不刪了嗎🧐當然不是,只是用的方法不是刪除,而是替代。如果我用一個合適的數去把我要刪除的這個數給替代掉,然后再將這個數原來所在的結點刪除,不就間接的完成了刪除而且不會破壞樹的結構了嗎😉,用的這個方法也可以叫做尋找替罪羊。

思路:

既然我們在替代后,還要刪除掉原來結點那么我們找的替罪羊(用來覆蓋cur的結點)必須容易刪除要不然就沒有意義,所以替罪羊至少具有兩點,1結點左右子樹必須有空的2大小必須合適,要滿足二叉搜索樹左邊比結點小右邊比結點大的特性

左右子樹必有空,只需要向下查找總能找到,那么我們現在要思考的是怎么找到大小合適的結點?

根據二叉搜索樹的的特性我們有兩種方法可以找到

  • 在cur的左邊找最大值
  • 在cur的右邊找最小值

這里我就使用在cur的右邊找最小值來演示,因為cur的右子樹都是比cur大的數,所以我們就要在其右子樹中找到比cur.right小的數就行,那么只需要找cur.right的左子樹不就好了😉,既比cur大(因為在cur右邊),又比cur.right小(因為在cur左邊)

所以根據上面的分析我們知道了我們要找的結點是cur.right的左子樹,并且這個替罪羊結點有空的子樹,如果能找到,這個空的結點必然是左子樹(如果左子樹還有結點證明還可以向下查找)最后用這個結點覆蓋掉cur,再刪掉就行😉

//在cur的左邊找最大值,同理找cur.left的右子樹如果能找到,他的右子樹必然是空的

//如果替罪羊結點就是cur.right就不能再往左邊找了,因為這時左邊已經為空了,所以要單獨判斷一下

😸性能分析

二叉搜索樹插入和刪除操作都必須先查找,查找效率代表了二叉搜索樹中各個操作的性能。 對有n個結點的二叉搜索樹,若每個元素查找的概率相等,則二叉搜索樹平均查找長度是結點在二叉搜索樹的深度 的函數,即結點越深,則比較次數越多。

最優情況下,二叉搜索樹為完全二叉樹,其平均比較次數為:logN

最差情況下,二叉搜索樹退化為單支樹,其平均比較次數為:N/2

🐭到這里我們就聊完了二叉搜索樹,如果你有什么不懂或者其他見解歡迎在下方評論或者私信博主,也可以希望多多支持一下博主!!!🥰🥰,我們下一個篇章聊一聊java中的map和set😸

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/19930.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/19930.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/19930.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言高級編程及實例剖析.pdf

C語言高級編程及實例剖析.pdf C語言&#xff0c;作為一種經典且強大的編程語言&#xff0c;已經在多個領域得到廣泛應用。然而&#xff0c;要想真正掌握C語言的高級編程技巧&#xff0c;卻并非易事。本文將深入探討C語言的高級編程技巧&#xff0c;并結合實例進行詳細剖析&…

61. UE5 RPG 實現敵人近戰攻擊技能和轉向攻擊

在前面&#xff0c;我們實現了敵人的AI系統&#xff0c;敵人可以根據自身的職業進行匹配對應的攻擊方式。比如近戰戰士會靠近目標后進行攻擊然后躲避目標的攻擊接著進行攻擊。我們實現了敵人的AI行為&#xff0c;但是現在還沒有實現需要釋放的技能&#xff0c;接下來&#xff0…

HTML5 音頻 Audio 標簽詳解

HTML5 引入了 <audio> 標簽&#xff0c;允許開發者在網頁中直接嵌入音頻文件&#xff0c;而不需要依賴第三方插件。本文將全面介紹 <audio> 標簽的各種屬性&#xff0c;并通過實例代碼詳細說明其用法。 一、基礎用法 1. 基本結構 HTML5 中使用 <audio> 標…

通過定時器和脈沖控制LED

目錄 一、定時器 &#xff08;一&#xff09;定時器簡介 &#xff08;二&#xff09;定時器類型 1、常見定時器 2、定時器的主要功能 3、常規定時器 &#xff08;三&#xff09;定時器配置 1、定時器標準外設庫接口函數 2、定時器標準外設庫配置 二、PWM &#xff08…

匿名函數(lambda)

自學python如何成為大佬(目錄):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 匿名函數是指沒有名字的函數&#xff0c;應用在需要一個函數&#xff0c;但是又不想費神去命名這個函數的場合。通常情況下&#xff0c;這樣的函數只…

【Qt】Qt界面美化指南:深入理解QSS樣式表的應用與實踐

文章目錄 前言&#xff1a;1. 背景介紹2. 基本語法3. QSS 設置方式3.1. 設置全局樣式3.2. 從文件加載樣式表3.3. 使用 Qt Designer 編輯樣式 總結&#xff1a; 前言&#xff1a; 在當今這個視覺至上的時代&#xff0c;用戶界面&#xff08;UI&#xff09;的設計對于任何軟件產…

智能制造案例專題|與MongoDB一起解鎖工業4.0轉型與增長的無限潛力!

MongoDB 智能制造 數字化技術的洪流在各個產業鏈的主干和枝節涌現。在工業制造領域&#xff0c;能否通過數字化技術實現各生產要素、生產環節之間的緊密配合&#xff0c;高效規劃、管理整個生產流程&#xff0c;是企業提升韌性、贏得競爭的關鍵。隨著工業4.0的深入發展和智能…

高級Java開發者的自我修養:深入剖析JVM垃圾回收機制及面試要點

在探索Java虛擬機&#xff08;JVM&#xff09;的奧秘過程中&#xff0c;垃圾回收機制&#xff08;GC&#xff09;是一個不可或缺的話題&#xff0c;尤其在面對大型應用和系統優化時顯得尤為重要。JVM的自動內存管理是Java編程語言中一項革命性的特性&#xff0c;它大大簡化了程…

測試記錄2:Ubuntu工程直接添加使用Eigen3源文件

直接將Eigen3源文件放入到工程目錄下使用&#xff0c;免安裝 1.新建空文件夾Test_eigen 2.創建將eigen下載的文件夾解壓&#xff0c;重命名為eigen3放入到Test_eigen 3.進入Test_eigen&#xff0c;創建main.cpp #include <iostream> #include <Eigen/Eigen>int m…

AI盒子在智慧加油站的應用

方案背景 為規范加油站作業&#xff0c;保障人民生命財產安全&#xff0c;《加油站作業安全規范》&#xff08;AQ 3010-2007&#xff09;中第五條規定&#xff1a;卸油作業基本要求&#xff0c;明確防靜電、防雷電、防火、人員值守、禁止其他車輛及非工作人員進入卸油區。 痛點…

數據結構基礎篇(4)

十六.循環鏈表 概念 循環鏈表是一種頭尾相接的鏈表&#xff08;最后一個結點的指針域指向頭結點&#xff0c;整個鏈表形成一個環&#xff09;優點 從表任一結點出發均可找到表中其他結點判斷終止 由于循環鏈表中沒有NULL指針&#xff0c;所以涉及遍歷操作時&#xff0c;終止條…

RocketMQ學習(2) 深入學習

RokcetMQ的介紹和基礎知識見這篇博客——RocketMQ學習(1) 快速入門 本篇為上一篇的深入學習&#xff0c;很多基礎知識不再贅述。 目錄 消息重復消費問題(去重;冪等)布隆過濾器 重試機制死信消息 SpringBoot集成RocketMQ集成SpringBoot發送不同消息模式(同步消息)異步消息單向消…

python下載指定URL的文件

import requests # 圖片的URL地址 url https://book.pep.com.cn/1212001402143/files/mobile/1.jpg?240301113921 # 發送HTTP GET請求 response requests.get(url) # 檢查請求是否成功 if response.status_code 200: # 打開一個文件用于寫入 with open(download…

實習碰到的問題w1

1.vueelementUI在輸入框中按回車鍵會刷新頁面 當一個 form 元素中只有一個輸入框時&#xff0c;在該輸入框中按下回車應提交該表單。如果希望阻止這一默認 行為&#xff0c;可以在 <el-form> 標簽上添加 submit.native.prevent 。 參考&#xff1a;element-ui 表單 form …

使用el-tab,el-tab-pane循環使用循環后不顯示下劃線問題

在vue項目中使用element-UI el-tab里的el-tab-pane是循環出來的&#xff0c;但是循環出來后選中tab不顯示下劃線了 文章目錄 問題問題展示效果問題代碼問題原因 解決方案解決后效果解決方案1代碼 解決方案2代碼 問題 問題展示效果 問題代碼 <el-tabs v-model"activeNa…

音量的對數表示與浮點數表示

音量用浮點數&#xff08;float&#xff09;和對數&#xff08;logarithmic scale&#xff09;表示各有特點和應用場景 浮點數&#xff1a;直接使用線性刻度表示音量&#xff0c;例如在0.0&#xff08;最小音量&#xff09;到1.0&#xff08;最大音量&#xff09;的范圍內。對…

『 Linux 』緩沖區(萬字)

文章目錄 &#x1f9a6; 什么是緩沖區&#x1f9a6; 格式化輸入/輸出&#x1f9a6; 刷新策略&#x1fab6; 塊緩沖(fully buffered)&#x1fab6; 無緩沖(unbuffered)&#x1fab6; 行緩沖(line buffered) &#x1f9a6; 現象解釋&#x1f9a6; exit()與_exit()&#x1f9a6; 進…

list 的實現

目錄 list 結點類 結點類的構造函數 list的尾插尾刪 list的頭插頭刪 迭代器 運算符重載 --運算符重載 和! 運算符重載 * 和 -> 運算符重載 list 的insert list的erase list list實際上是一個帶頭雙向循環鏈表,要實現list,則首先需要實現一個結點類,而一個結點需要…

【代碼隨想錄——回溯算法——四周目】

1.重新安排行程 1.1 我的代碼&#xff0c;超時通不過 var (used []boolpath []stringres []stringisFind bool )func findItinerary(tickets [][]string) []string {sortTickets(tickets)res make([]string, len(tickets)1)path make([]string, 0)used make([]bool,…

JSON Web Token

JWT 什么是JWT JWT&#xff08;JSON Web Token&#xff09;是一種用于在各方之間作為JSON對象安全地傳輸信息的開放標準&#xff08;RFC 7519&#xff09;。該信息經過數字簽名&#xff0c;因此是可驗證和可信的。JWT 可以使用HMAC算法或使用RSA的公鑰/私鑰對進行簽名 JWT的…