《二叉搜索樹》

引言:

上次我們結束了類和對象的收尾,之后我們就要學習一些高級的數據結構,今天我們先來看一個數據結構-- 二叉搜索樹。

一: 二叉搜索樹的概念(性質)

二叉搜索樹又稱二叉排序樹,它或者是一棵空樹,或者是具有以下性質的二叉樹:

  1. 若它的左子樹不為空,則左子樹上所有結點的值都小于等于根結點的值。
  2. 若它的右子樹不為空,則右子樹上所有結點的值都大于等于根結點的值。
  3. 它的左右子樹也分別為二叉搜索樹
  4. 二叉搜索樹中可以支持插入相等的值,也可以不支持插入相等的值,具體看使用場景定義,后續我們學習map/set/multimap/multiset系列容器底層就是二叉搜索樹,其中map/set不支持插入相等值,multimap/multiset支持插入相等值。

左圖就是map不支持插入相同的數據。
右圖就是multimap支持插入相同的數據。
在這里插入圖片描述

二:二叉搜索樹的性能分析:

最優情況下,二叉搜索樹完全二叉樹(或者接近完全二叉樹),其高度為: log2N
最差情況下,二叉搜索樹退化為單支樹(或者類似單支),其高度為:N
所以綜合而言二叉搜索樹增刪查改時間復雜度為:O(N)
在這里插入圖片描述
那么這樣的效率顯然是無法滿足我們需求的,我們后續會接著學習二叉搜索樹的變形,平衡二叉搜索樹AVL樹)和紅黑樹,才能適用于我們在內存中存儲和搜索數據。
另外需要說明的是,二分查找也可以實現o(log2N)級別的查找效率,但是二分查找有兩大缺陷:

  1. 需要存儲在支持下標隨機訪問的結構中,并且有序
  2. 插入和刪除數據效率很低,因為存儲在下標隨機訪問的結構中,插入和刪除數據一般需要挪動數據
    因此這里也就體現出了平衡二叉搜索樹的價值。

三:模擬實現二叉搜索樹

1. 基本框架:

因為二叉搜索樹二叉樹衍生而來的,因此其基本結構和二叉樹差不多,因此這里我們就不細講:
在這里插入圖片描述

2. 插入數據:

(1)插入原則:

插入的具體過程如下:

  1. 樹為空,則直接新增結點,賦值給root指針。
  2. 樹不空,按二叉搜索樹性質,插入值比當前結點大往右走,插入值比當前結點小往左走,找到空位置,插入新結點。
  3. 如果支持插入相等的值,插入值跟當前結點相等的值可以往右走,也可以往左走,找到空位置,插入新結點。(要注意的是要保持邏輯一致性,插入相等的值不要一會往右走,一會往左走,但是這里我們實現的是不支持插入相同數據的)
(2)思路分析:

在這里插入圖片描述

(3)補充:在這里插入圖片描述

注:由于插入數據的時候牽扯到數據的申請,因此這里的節點結構要提供對于的構造函數來生成節點。

(4)代碼實現:

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

(5)測試:

注:這里為了測試插入數據,因此我們再實現一個中序遍歷。

中序遍歷實現:

在這里插入圖片描述
在這里插入圖片描述
可以看到測試結果沒有問題。

3. 查找數據:

(1)查找原則:

從根開始比較,查找x,x比根的值大則往右邊走查找,x比根值小則往左邊走查找。
2. 最多查找高度次,走到空,還沒找到,這個值不存在。
3. 如果不支持插入相等的值,找到x即可返回。
4. 如果支持插入相等的值,意味著有多個x存在,一般要求查找中序的第一個x。如下圖,查找3,要找到1的右孩子的那個3返回。

在這里插入圖片描述

(2)思路分析:

查找的邏輯和插入的邏輯基本上一樣,就不再具體分析。

(3) 代碼實現:

在這里插入圖片描述

(4)測試:

在這里插入圖片描述
測試沒問題。

4. 刪除數據:

相較于插入數據,刪除數據就比較復雜了,需要考慮各種情況,下面我們來一點點分析:
首先查找元素是否在二叉搜索樹中,如果不存在,則返回false
如果查找元素存在則分以下四種情況分別處理:(假設要刪除的結點為N)

  1. 要刪除結點N左右孩子均為空。
  2. 要刪除的結點N左孩子位空,右孩子結點不為空。
  3. 要刪除的結點N右孩子位空,左孩子結點不為空。
  4. 要刪除的結點N左右孩子結點均不為空。
    對應以上四種情況的解決方案:
  5. 把N結點的父親對應孩子指針指向空,直接刪除N結點(情況1可以當成2或者3處理,效果是一樣的)
  6. 把N結點的父親對應孩子指針指向N的右孩子,直接刪除N結點。
  7. 把N結點的父親對應孩子指針指向N的左孩子,直接刪除N結點。
  8. 無法直接刪除N結點,因為N的兩個孩子無處安放,只能用替換法刪除。找N左子樹的值最大結點R(最右結點)或者N右子樹的值最小結點R(最左結點)替代N,因為這兩個結點中任意一個,放到N的位置,都滿足二叉搜索樹的規則。替代N的意思就是N和R的兩個結點的值交換,轉而變成刪除R結點,R結點符合情況2或情況3,可以直接刪除。
(1) 思路分析:

在這里插入圖片描述
在這里插入圖片描述

(2)代碼實現:

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述在這里插入圖片描述

(3) 測試:

在這里插入圖片描述

5. 銷毀

(1)思路分析:

跟之前我們的二叉樹銷毀一樣,只需要后序遍歷來銷毀即可。

(2) 代碼實現:

在這里插入圖片描述

6. 拷貝構造函數

這里跟之前二叉樹的構建一樣,只需要一邊遍歷一邊構建即可。

(2)代碼實現:

在這里插入圖片描述
在這里插入圖片描述

(3)測試:

在這里插入圖片描述

7. 賦值運算符重載:

(1)思路分析:

這里的賦值運算符重載和之前差不多,還是復用拷貝構造函數。

(2)代碼實現:

在這里插入圖片描述

(3)測試:

在這里插入圖片描述

完結!!!

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

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

相關文章

【Redis】Sentinel哨兵

🛡? 深入理解 Redis Sentinel:高可用架構的守護者 在實際開發中,我們常用 Redis 構建緩存系統或數據中間件。然而,主從復制雖然能實現數據同步,但無法自動故障轉移(failover),這就…

Shell腳本應用及實戰演練

文章目錄 一、Shell腳本語言的基本結構1、Shell腳本的用途:2、 Shell腳本基本結構:3、 創建Shell腳本過程4、 腳本注釋規范 二、Shell腳本語言的變量用法詳解位置與預定義變量 三、 Shell字符串詳解1、Shell字符串拼接2、Shell字符串截取3、 Shell的格式…

軟件工程瀑布模型學習指南

軟件工程瀑布模型學習指南 一、瀑布模型核心概念 1.1 定義與特點 瀑布模型是一種經典的軟件開發流程,將項目劃分為順序性的階段,每個階段有明確的輸入和輸出,如同瀑布流水般單向推進。其特點包括: 階段間具有明確的順序性和依賴性強調文檔驅動和階段評審適合需求明確、穩…

獲取gitlab上項目分支版本(二)

獲取gitlab上項目分支版本_gitlab代碼分支版本在哪-CSDN博客 原先寫過一版,但是這次想更新一下項目的分支信息時,提示我 git服務器上的Python版本是2.7.3,這個錯誤表明當前Python環境中沒有安裝requests庫,服務器也沒有連接外網&…

主流防火墻策略繞過漏洞的修復方案與加固實踐

主流防火墻策略繞過漏洞的修復方案與加固實踐 流量關鍵點分析(攻擊手法) 攻擊者通過精心構造的TCP序列號攻擊和惡意標志組合繞過防火墻DPI檢測,核心手法如下: TCP連接建立(正常握手) 1049:客戶…

泛微OAe9-后端二開常見數據庫操作

泛微OAe9-后端二開常見數據庫操作 文章目錄 泛微OAe9-后端二開常見數據庫操作一、RecordSet1 RecordSet 操作OA本身的表2 RecordSet 操作OA 本身的存儲過程 二、RecordSetTrans三、RecordSetDataSource四、原生 jdbc 一、RecordSet RecordSet 適用于操作 OA 自己的庫。OA 數據庫…

【數據分析八:hypothesis testing】假設檢驗

本節我們講述假設檢驗和抽樣方法 有關假設檢驗的詳細內容,可以參考我以往的博客 概率論與數理統計總復習_概率論與數理統計復習-CSDN博客文章瀏覽閱讀1.5k次,點贊33次,收藏23次。中科大使用的教輔《概率論和數理統計》,帶大家復…

AI免費工具:promptpilot、今天學點啥、中英文翻譯

promptpilot 激發模型潛能,輕松優化 Prompt https://promptpilot.volcengine.com/startup 今天學點啥 https://metaso.cn/study 能生成網頁和語音播報 中英文翻譯 沉浸式翻譯,瀏覽器插件,ai翻譯

計算機網絡學習筆記:TCP三報文握手、四報文揮手

文章目錄 前言一、TCP三報文握手二、TCP四報文揮手三、TCP保活計時器 前言 TCP通信,通常需要經歷三個階段:三報文握手->發送,接收數據->四報文揮手。 一、TCP三報文握手 三報文握手處于TCP的連接建立階段,主要解決了以下的…

kafka部署和基本操作

一、部署kafka 解壓 tar xzvf kafka_2.12-3.9.1.tgz tar -zxf kafka_2.12-3.9.1.tgz 1.修改config/server.properties # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # …

Bootstrap 5學習教程,從入門到精通,Bootstrap 5 導航語法知識點及案例代碼(17)

Bootstrap 5 導航語法知識點及案例代碼 Bootstrap 5 提供了強大的導航組件,幫助開發者快速構建響應式且美觀的導航欄。 一、Bootstrap 5 導航組件概述 Bootstrap 5 提供了多種導航組件,主要包括: 導航欄(Navbar)&am…

清除 docker 無用的 鏡像/容器

清除 docker 無用的 鏡像/容器 刪除 <none> 的 docker 鏡像 使用以下命令刪除所有 的 Docker 鏡像&#xff08;即懸空鏡像 / dangling images&#xff09;&#xff1a; docker image prune -f這會自動刪除所有沒有 tag 的鏡像&#xff08;&#xff09;&#xff0c;不會…

使用Charles抓包工具提升API調試與性能優化效率

在軟件開發過程中&#xff0c;網絡請求調試和性能優化往往成為開發者遇到的挑戰&#xff0c;尤其是在進行API接口調試時。開發者需要確保網絡請求的正確性、響應時間以及系統的整體性能。然而&#xff0c;傳統的調試方法常常無法提供足夠的細節來深入分析問題&#xff0c;進而影…

如何協調各項目關鍵節點的沖突與依賴

在多項目并行的環境下&#xff0c;關鍵節點間的沖突與依賴是導致項目延期、資源浪費和溝通誤解的主要根源。要高效協調此類問題&#xff0c;企業應重點從建立透明的進度依賴圖、使用項目管理工具對齊節點、推動跨部門協同機制入手。其中&#xff0c;通過Gantt圖或關鍵路徑法實現…

mongodb單節點改副本集模式

前一陣將三節點的副本集改成了單節點&#xff0c;但后面業務代碼出現問題&#xff1a;無法使用事務&#xff0c;因為事務只有在副本集上能用&#xff0c;單節點無法使用&#xff0c;故需要改回副本集模式&#xff0c;而我目前僅有一臺服務器&#xff0c;所以考慮在一臺服務器上…

Android 修改了頁面的xml布局,使用了databinding,這時候編譯時需要用到apt嗎

deepseek回答&#xff1a; 在 Android 開發中使用 DataBinding 時&#xff0c;不需要顯式使用 apt&#xff08;Annotation Processing Tool&#xff09;。以下是詳細說明&#xff1a; 1. DataBinding 的編譯機制 DataBinding 是 Android Gradle 插件原生支持的功能&#xff…

服務器如何從http升級到https(nginx)

1.證書申請 可以到阿里云或者華為云去申請證書&#xff0c;申請完下載證書是個壓縮包&#xff0c;然后解壓 可以到到幾個文件夾&#xff0c;找到 .Nginx 文件夾打開 會有兩個文件&#xff0c;將這兩個文件上傳至nginx/conf/cert文件夾下&#xff08;cert需要手…

6.19_JAVA_微服務

1、跑后端的時候要把數據庫跑起來&#xff0c;否則會報錯。 2、predicate斷言&#xff1a; 預言&#xff1a;predict 3、gateway&#xff1a;出路口 4、API&#xff1a;List.of("a", "b", "c");把abc編程一個集合。 5、 6、shortcutFieldOrd…

Linux 基礎命令:`ls`、`cd`、`du` 快速入門

在 Linux 系統中&#xff0c;ls、cd 和 du 是日常操作中最常用的三個命令。掌握它們能大幅提升文件管理效率。 1. ls&#xff1a;查看目錄內容 用途&#xff1a;列出當前或指定目錄下的文件和子目錄。 常用命令&#xff1a; ls -l # 詳細列表&#xff08;權限、大…

408第一季 - 數據結構 - 散列表

散列表 概念 散列表本身就是為了查找 原始人思想 散列表思想 6%5 是 1 1%5 也是1 沖突 沖突怎么辦&#xff1f; 線性探測法 就往后找&#xff0c;1跑到索引為2 然后查找&#xff0c;可以發現&#xff0c;只要沒沖突就只用查找1次 然后你想找10的話&#xff0c;發現索引為0…