《數據結構:二叉搜索樹(Binary Search Tree)》

文章目錄

    • :red_circle:一、二叉搜索樹的概念
    • :red_circle:二、二叉搜索樹的性能分析
    • :red_circle:三、二叉搜索樹的操作
      • (一)插入
      • (二)查找
      • (三)刪除
    • :red_circle:四、二叉搜索樹的實現代碼
      • (一)結構體 `BSTNode`
      • (二)類 `BSTree`
    • :red_circle:五、二叉搜索樹的應用場景
      • (一)key搜索場景
      • (二)key/value搜索場景
    • :red_circle:六、總結
    • 如果有幫助的話麻煩點個贊和關注吧,秋梨膏QAQ!

作者的個人gitee??

作者的算法講解主頁??

每日一言:“人生如逆旅,我亦是行人。🌸🌸”


🔴一、二叉搜索樹的概念

二叉搜索樹(Binary Search Tree,BST)是一種特殊的二叉樹,具有以下性質:

  • 若左子樹不為空,則左子樹上所有結點的值都小于等于根結點的值。
  • 若右子樹不為空,則右子樹上所有結點的值都大于等于根結點的值。
  • 左右子樹也分別為二叉搜索樹。
  • 二叉搜索樹中可以支持插入相等的值,也可以不支持,具體取決于使用場景的定義。如,在C++標準模板庫中,mapset不支持插入相等值,而multimapmultiset支持插入相等值。

在這里插入圖片描述

🔴二、二叉搜索樹的性能分析

二叉搜索樹的性能主要取決于其高度。以下是不同情況下的性能分析:

情況高度增刪查改時間復雜度
最優logNO(logN)
最差NO(N)
平均取決于插入順序取決于插入順序
  • 最優情況當二叉搜索樹為完全二叉樹或接近完全二叉樹時,其高度為log2N。此時增刪查改的時間復雜度為 O(log2N)。
  • 最差情況當二叉搜索樹退化為單支樹或類似單支時,其高度為N。此時增刪查改的時間復雜度為O(N)。
  • 平均情況:在實際應用中,二叉搜索樹的高度取決于插入數據的順序。如果插入數據是隨機的,那么平均情況下二叉搜索樹的性能接近最優情況;但如果插入數據是有序的,那么二叉搜索樹可能會退化為單支樹,性能接近最差情況。

在這里插入圖片描述

🔴三、二叉搜索樹的操作

(一)插入

插入操作的步驟如下:

  1. 樹為空:如果二叉搜索樹為空,則直接創建一個新的結點,并將其賦值給根指針。
  2. 樹不為空:從根結點開始,按照二叉搜索樹的性質進行比較:
    • 如果插入值小于當前結點的值,則向左子樹移動。
    • 如果插入值大于當前結點的值,則向右子樹移動。
    • 如果插入值等于當前結點的值(支持插入相等值的情況),可以選擇向左或向右移動,但需要保持邏輯一致性。
  3. 找到空位置:當找到一個空位置時,創建一個新的結點,并將其插入到該位置。

(二)查找

查找操作的步驟如下:

  1. 從根開始:從根結點開始,將目標值與當前結點的值進行比較。
  2. 比較并移動
    • 如果目標值小于當前結點的值,則向左子樹移動。
    • 如果目標值大于當前結點的值,則向右子樹移動。
  3. 查找結果
    • 如果在某個結點找到目標值,則返回該結點。
    • 如果走到空結點仍未找到目標值,則說明目標值不存在。

(三)刪除

刪除操作相對復雜,需要分情況處理:

情況描述解決方案
1要刪除結點N左右孩子均為空把N結點的父母對應孩子指針指向空,直接刪除N結點
2要刪除的結點N左孩子為空,右孩子結點不為空把N結點的父母對應孩子指針指向N的右孩子,直接刪除N結點
3要刪除的結點N右孩子為空,左孩子結點不為空把N結點的父母對應孩子指針指向N的左孩子,直接刪除N結點
4要刪除的結點N左右孩子結點均不為空無法直接刪除N結點,用替換法刪除。找N左子樹的值最大結點R(最右結點)或者N右子樹的值最小結點R(最左結點)替代N,然后變成刪除R結點,R結點符合情況2或情況3,可以直接刪除

🔴四、二叉搜索樹的實現代碼

(一)結構體 BSTNode

template<class K>
struct BSTNode
{K _key;BSTNode<K>* _left;BSTNode<K>* _right;BSTNode(const K& key): _key(key), _left(nullptr), _right(nullptr) {}
};

(二)類 BSTree

template<class K>
class BSTree
{typedef BSTNode<K> Node;
public:bool Insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false; // 不允許插入重復值}}cur = new Node(key);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}bool Find(const K& key){Node* cur = _root;while (cur){if (cur->_key < key){cur = cur->_right;}else if (cur->_key > key){cur = cur->_left;}else{return true; // 找到目標值}}return false; // 未找到目標值}bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{// 情況1:左右孩子均為空if (cur->_left == nullptr && cur->_right == nullptr){if (parent == nullptr){_root = nullptr;}else{if (parent->_left == cur)parent->_left = nullptr;elseparent->_right = nullptr;}delete cur;return true;}// 情況2:左孩子為空,右孩子不為空else if (cur->_left == nullptr){if (parent == nullptr){_root = cur->_right;}else{if (parent->_left == cur)parent->_left = cur->_right;elseparent->_right = cur->_right;}delete cur;return true;}// 情況3:右孩子為空,左孩子不為空else if (cur->_right == nullptr){if (parent == nullptr){_root = cur->_left;}else{if (parent->_left == cur)parent->_left = cur->_left;elseparent->_right = cur->_left;}delete cur;return true;}// 情況4:左右孩子均不為空else{Node* rightMinP = cur;Node* rightMin = cur->_right;while (rightMin->_left){rightMinP = rightMin;rightMin = rightMin->_left;}cur->_key = rightMin->_key;if (rightMinP->_left == rightMin)rightMinP->_left = rightMin->_right;elserightMinP->_right = rightMin->_right;delete rightMin;return true;}}}return false; // 未找到目標值}void InOrder(){_InOrder(_root);cout << endl;}private:void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}Node* _root = nullptr;
};

🔴五、二叉搜索樹的應用場景

(一)key搜索場景

在key搜索場景中,二叉搜索樹僅存儲關鍵碼(key),用于判斷某個值是否存在。

  • 小區無人值守車庫:將買了車位的業主車牌號錄入后臺系統,車輛進入時掃描車牌號,判斷其是否存在于系統中,從而決定是否抬桿。
  • 英文單詞拼寫檢查:將詞庫中的所有單詞放入二叉搜索樹,讀取文章中的單詞,查找其是否存在于二叉搜索樹中,若不存在則提示拼寫錯誤。

(二)key/value搜索場景

在key/value搜索場景中,二叉搜索樹的每個結點不僅存儲關鍵碼(key),還存儲與之對應的值(value)。搜索時以key為關鍵字進行比較,可以快速找到key對應的value。

  • 中英互譯字典:在樹的結點中存儲英文單詞(key)和對應的中文翻譯(value),搜索時輸入英文單詞,即可找到其對應的中文翻譯。
  • 商場無人值守車庫:入口進場時掃描車牌號,記錄車牌號和入場時間(key/value),出口離場時掃描車牌號,查找入場時間,計算停車時長和費用。
  • 統計文章中單詞出現次數:讀取一個單詞,查找其是否存在于二叉搜索樹中,若不存在則插入該單詞并將其出現次數初始化為1,若存在則將其對應的出現次數加1。

🔴六、總結

二叉搜索樹是一種重要的數據結構,具有插入、查找、刪除等操作。其性能在最優情況下接近O(log2N),但在最差情況下會退化為O(N)。為了提高二叉搜索樹的性能,后續可以學習其進階,如平衡二叉搜索樹(AVL樹)、B樹和紅黑樹。


如果有幫助的話麻煩點個贊和關注吧,秋梨膏QAQ!

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

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

相關文章

【Linux相關】實時查看Nvidia-smi使用情況

【Linux相關】 實時查看Nvidia-smi使用情況 文章目錄 實時查看Nvidia-smi使用情況 實時查看Nvidia-smi使用情況 在本地終端執行下述語句 watch -n 1 nvidia-smi每一秒都會更新&#xff0c;將 1 改為其他數字可以滿足不同需求

Kotlin密封類優化Android狀態管理

Kotlin 的密封類&#xff08;Sealed Class&#xff09;確實是 Android 開發中管理復雜 UI 狀態的利器。它通過類型安全的層次結構&#xff0c;讓狀態管理代碼更加清晰簡潔。讓我們從實際開發場景出發&#xff0c;深入探討其應用&#xff1a; 一、密封類核心優勢 受限的類繼承…

JavaWeb:SpringBootWeb快速入門

介紹 Spring SpringBoot 入門程序 需求 步驟 修改端口 1.新建application.yml #設置端口 server:port: 8081入門程序-分析 為什么main方法能啟動web應用-內嵌tomcat 為什么tomcat能定位HelloController程序 請求先到DisPatcherServlet&#xff0c;根據路徑轉發 小結 1.…

Unity學習筆記二

文章目錄 3D數學公共計算結構體Mathf常用成員三角函數 向量Vector3基本成員點乘叉乘插值運算 四元數引出基本概念Quaternion結構體成員四元數運算 更多的Mono延遲函數協同程序多線程相關協程概念辨析協程本體協程調度器 Resources資源動態加載特殊文件夾Resources同步加載Resou…

為什么Transformer推理需要做KV緩存

一、我們先來回憶一下在transformer中KV在哪里出現過&#xff0c;都有什么作用&#xff1f; α的計算過程&#xff1a; 這里引入三個向量&#xff1a; 圖中的q為Query&#xff0c;用來匹配key值 圖中的k為key,用來被Query匹配 圖中的Value&#xff0c;是用來被進行加權平均的 由…

【大模型面試】大模型(LLMs)高頻面題全面整理(★2025年5月最新版★)

【大模型面試】大模型&#xff08;LLMs&#xff09;高頻面題全面整理&#xff08;★2025年5月最新版★&#xff09; &#x1f31f; 嗨&#xff0c;你好&#xff0c;我是 青松 &#xff01; &#x1f308; 自小刺頭深草里&#xff0c;而今漸覺出蓬蒿。 本筆記適合大模型初學者和…

JAVA:使用 iTextPDF 處理 PDF 的技術詳解

1、簡述 iTextPDF 是一個功能強大的 Java PDF 庫,可以用來創建、修改和處理 PDF 文檔。通過它,我們可以完成如生成 PDF、讀取 PDF 內容、添加水印、合并 PDF 等多種操作。本篇博客將詳細介紹 iTextPDF 的使用方法,并提供一些實踐樣例,幫助開發者快速上手。 樣例代碼: htt…

模態與非模態窗口及使用時的數據交互

模態窗口使用exec()方法顯示&#xff0c;會阻塞父窗口&#xff0c;直到對話框關閉&#xff1b; 非模態對話框允許同時操作主窗口和設置窗口&#xff0c;使用show()。 模態和非模態的主要區別在于用戶能否與父窗口交互&#xff0c;非模態更適合需要頻繁切換的場景。非模態窗口需…

Docker進入MySQL之后如何用sql文件初始化數據

關閉Docker-compose.yml里面所有容器 docker compose -f docker_compose.yml down后臺形式開啟Docker-compose.yml所有容器 docker compose -f docker_compose.yml up -d羅列出所有啟動過的&#xff08;包括退出過的&#xff09;容器 docker ps -a進入指定容器ID內部 docke…

MAC 地址

MAC地址&#xff08;Media Access Control Address&#xff09;是指網絡設備在數據鏈路層使用的唯一標識符&#xff0c;也稱為硬件地址或物理地址。它用于標識設備之間的網絡通信&#xff0c;是網絡適配器&#xff08;如網卡、Wi-Fi適配器等&#xff09;的唯一標識。每個網絡設…

Redis 7.0中5種新特性及實戰應用

Redis 7.0引入了多項革命性的新特性&#xff0c;不僅在性能和可靠性方面有所提升&#xff0c;更在功能和使用體驗上有了質的飛躍。本文將介紹Redis 7.0的五大關鍵新特性&#xff0c;可以根據實際情況利用Redis 7.0的強大功能&#xff0c;構建更高效、更可靠的應用系統。 特性一…

PHP實現PDF自動簽名

技術要點&#xff1a;在PDF中找到一個固定錨點&#xff0c;在需要放置圖片的地方找到測試出錨點對應的XY位 // 使用了poppler方法&#xff0c;其他PDF庫在獲取坐標方面有各種問題&#xff0c;他的安裝是在Linux底層&#xff0c;比在PHP項目中用Composer安裝的庫看上去更穩定&a…

中達瑞和便攜式高光譜相機:珠寶鑒定領域的“光譜之眼”

在珠寶行業中&#xff0c;真偽鑒定始終是核心需求。隨著合成技術與優化處理手段的日益精進&#xff0c;傳統鑒定方法逐漸面臨挑戰。中達瑞和推出的便攜式高光譜相機&#xff0c;憑借其獨特的“圖譜合一”技術&#xff0c;為珠寶真假鑒定提供了科學、高效且無損的解決方案&#…

2025年滲透測試面試題總結-某戰隊紅隊實習面經(附回答)(題目+回答)

網絡安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 某戰隊紅隊實習面經 個人經歷與技術能力 2. HVV/攻防演練成績 3. 上一個工作主要內容 4. 有意思的邏…

【PostgreSQL數據分析實戰:從數據清洗到可視化全流程】5.1 描述性統計分析(均值/方差/分位數計算)

&#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 文章大綱 5.1 描述性統計分析&#xff1a;均值、方差與分位數計算實戰5.1.1 數據準備與分析目標數據集介紹分析目標 5.1.2 均值計算&#xff1a;從整體到分組分析總體均值計算加權均值…

npm下載插件無法更新package.json和package-lock.json文件的解決辦法

經過多番查證&#xff0c;使用npm config ls查看相關配置等方式&#xff0c;最后發現全局的.npmrc文件的配置多寫了globaltrue&#xff0c;去掉就好了 如果參數很多&#xff0c;不知道是哪個參數引起的&#xff0c;先只保留registryhttp://xxx/&#xff0c;試試下載&#xff0…

基于Anaconda的Pycharm環境配置

一、前提條件&#xff1a; 1、默認已安裝完Anaconda&#xff0c;且創建虛擬環境&#xff0c;參見https://blog.csdn.net/XIAOWEI_JIN/article/details/147657029?spm1001.2014.3001.5501 2、已安裝pycharm&#xff0c;下載鏈接見Pycharm官網&#xff0c;以下以PyCharm 2024.…

Word域操作記錄(從1開始的畢業論文格式排版)

傻逼Word。 寫在最前面 如果你的文章不包括&#xff1a;自動目錄、交叉引用、自動題注。請關閉此頁面。繼續閱讀本文是在浪費您用于跟格式如泥潭里纏斗的時間。 本文內容概述 從指導手冊到畢設初稿 基于多級列表的自動目錄生成方法 正片開始 關于文字 拿到畢設手冊&#…

Linux中的web服務

什么是www www是world wide web的縮寫&#xff0c;及萬維網&#xff0c;也就是全球信息廣播的意思 通常說的上網就是使用www來查詢用戶所需要的信息。 www可以結合文字、圖形、影像以及聲音等多媒體&#xff0c;超鏈接的方式將信息以Internet傳遞到世界各 處去。 當你連接w…

linux -c程序開發

目的是在linux中創建可執行的c語言程序的步驟 和gcc,make和git的簡單運用 建立可執行程序的步驟: -1:預處理: --:頭文件展開;--去掉注釋;--宏替換;--條件編譯 -2:編譯 --:將預處理之后的c語言替換為匯編語言帶阿米 --:語法分析,語義分析,代碼生成 --:檢查語法正確性并且優…