搜索二叉樹

目錄

搜索二叉樹的性質

搜索二叉樹的實現、

插入

?刪除

?代碼


在以前我們學過二叉樹,但是在對二叉樹的學習中發現,似乎二叉樹并沒有什么作用,要論增刪它比不上鏈表,論隨機訪問也沒法和順序表比,對于當時的我們是一頭霧水,那么現在它的功能終于是體現出來了,這里就是我們要講的搜索二叉樹。

搜索二叉樹的性質

在這里我們先了解一下什么是搜索二叉樹,搜索二叉樹,顧名思義它要滿足搜索的特征,于是就有人想出來一個辦法,我能不能在創建一個樹的時候,比它小的值放在左子樹,比它大的值放在右子樹呢,這樣的話當我們要去尋找某一個節點的時候,只需要比較一下左右子樹,如果這個值大就往它的右邊走,比它小就往它的左邊走呢。

?比如這里就是我們的一顆搜索二叉樹,當我們要去尋找一個值為6的時候,我就可以先和它的根節點比,小走左邊,大走右邊。

?按照這個特性,只要一顆搜索二叉樹被建立出來了,那么想要尋找一個值是不是時間效率非常的高?答案是否的,在某一個情況下我們想要尋找一個節點消耗的時間也是非常困難的

?比如說是這樣的一個搜索二叉樹,它在圖形上有點像我們的單鏈表,這樣的一棵樹如果要去尋找某個節點值的時候效率也是會達到o(N)的。

如果我們在仔細觀察一下的話,會發現如果我們對這課樹走一個中序遍歷的話得到的值會是一個有序的。例如這棵樹,如果中序走出來就是

1->3->4->6->7->8->10->13->14

所以我們現在知道二叉樹的特性大概有

它的左子樹必須是比根節點要小的

它的右子樹必須是比根節點要大的

它的中序遍歷一定是有序的

搜索二叉樹的實現、

插入

要創建一顆二叉樹,那么我們在插入數據的時候就要按照二叉樹的特征來進行插入,創建很簡單,只需要依次尋找,比它小往左,比它大往右,知道找到為空的那個未知就是我們需要插入的值,但是會有一個問題,找到當前為空的時候直接插入并沒有把當前節點和這顆樹聯系起來,所以還要記錄一下它的父親節點。但是這里我們用另一種思路,那么就是傳入的時候用引用,這樣下一個節點就是上一個節點的引用,給當前節點賦值實際是給上一個節點的左右子樹來賦值

?刪除

插入看出來其實很簡單,這里難的是我們的刪除。要刪除一個結點可能會遇到四種情況

a. 要刪除的結點無孩子結點
b. 要刪除的結點只有左孩子結點
c. 要刪除的結點只有右孩子結點
d. 要刪除的結點有左、右孩子結點
?

如果要刪除的是葉子結點,那么可以直接刪除,如果要刪除有左孩子就要考慮如果講左孩子鏈接道父親結點,如果是有右孩子就要考慮如果講右孩子鏈接上去。如果左右孩子都有這里就要考慮另一種方法替換法。

那么什么是替換法,這里加入我們需要刪除的節點為8,那么我們可以選擇讓左子樹最大的節點來替代它。

?這里還要注意一個問題,當我們用左子樹最大的機電替換之后需要從左子樹的第一個節點作為根節點開始尋找,如果用第一個節點來尋找的話第一次比較比當前節點大會往右邊走,最后導致找不到這個節點

?代碼

#pragma once
#include<iostream>using namespace std;template<class K>
struct BSNode
{BSNode* _left;BSNode* _right;K _key;BSNode(const K& key):_left(nullptr),_right(nullptr),_key(key){}
};template<class K>
class BSTree
{
public:typedef BSNode<K> Node;BSTree():_root(nullptr){}BSTree(const BSTree<int>& t){_root = _copy(t._root);}bool FindR(const K& key){return _FindR(_root,key);}bool Insert(const K& key){return _Insert(_root, key);}void Inorder(){_Inorder(_root);}bool erase(const K& key){return _erase(_root, key);}~BSTree(){destor(_root);}
private:Node* _copy(const Node* t){if (t == nullptr)return nullptr;Node* copynode = new Node(t->_key);copynode->_left = _copy(t->_left);copynode->_right = _copy(t->_right);return copynode;}bool _Insert(Node*& root,const K& key){if (root == nullptr){root = new Node(key);		//這里可以直接這樣插入是因為當前結點是root-左右指向的引用return true;}//開始往左右兩邊去找插入的未知if (root->_key < key){return _Insert(root->_right,key);	}else if (root->_key > key){return _Insert(root->_left, key);}else{return false;}}bool _erase(Node*& root, const K& key){if (root == nullptr)		//先判斷是否為空樹return false;if (root->_key < key)	//如果要刪除的值比當前節點大{	return _erase(root->_right,key);	//開始往右邊遞歸}else if (root->_key > key)	//如果要刪除的值比當前節點小{return _erase(root->_left,key);	//開始往左邊遞歸}else{//刪除有左或右孩子的情況if (root->_left == nullptr)	//如果它的左子樹為空{root = root->_right;	//那么就讓它的右節點等于當前節點}else if (root->_right == nullptr)//如果它的右子樹為空{root = root->_left;//那么就讓它的左節點等于當前節點}//左右都有孩子的情況else{Node* del = root;Node* leftMax = root->_left;	while (leftMax->_right){leftMax = leftMax->_right;	//用左孩子最大的節點來替換當前要刪除的節點}swap(root->_key, leftMax->_key);_erase(root->_left, key);	//這里不能從第一個節點開始找,因為當前樹的節點已經被替換過了,如果從第一個節點開始找會導致找不到這個節點del = leftMax;	delete del;	//找到之后刪除當前節點return true;}}}bool _FindR(const Node* root,const K& key){if (root == nullptr)return false;if (root->_key < key){return _FindR(root->_right);}else if (root->_key > key){return _FindR(root->_left);}else{return true;}}void _Inorder(Node* root){if (root == nullptr)return;_Inorder(root->_left);cout << root->_key << " ";_Inorder(root->_right);}void destor(Node* root){if (root == nullptr)return;destor(root->_left);destor(root->_right);delete root;root = nullptr;}Node* _root;
};//測試#pragma once#include"RecursiveBinarySearchTree.h"
using namespace std;int main()
{int arr[] = { 8,3,10,1,6,14,4,7,13 };BSTree<int> t;for (auto e : arr){t.Insert(e);}t.Inorder();t.erase(6);t.erase(1);t.erase(8);t.erase(13);cout << endl;t.Inorder();cout << endl;BSTree<int> t1(t);t1.Inorder();return 0;
}

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

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

相關文章

[Go版]算法通關村第十一關白銀——位運算的高頻算法題

目錄 專題1&#xff1a;位移的妙用題目&#xff1a;位1的個數&#xff08;也被稱為漢明重量&#xff09;解法1&#xff1a;遍歷所有位&#xff0c;判斷每個位的數字是否是1Go代碼 解法2&#xff1a;依次消除每個1的位 numnum&(num-1)Go代碼 題目&#xff1a;比特位計數思路…

Mac 卸載appium

安裝了最新版的appium 2.0.1,使用中各種問題&#xff0c;卡頓....,最終決定回退的。記錄下卸載的過程 1.打開終端應用程序 2.卸載全局安裝的 Appium 運行以下命令以卸載全局安裝的 Appium&#xff1a; npm uninstall -g appium 出現報錯&#xff1a;Error: EACCES: permiss…

云安全攻防(十二)之 手動搭建 K8S 環境搭建

手動搭建 K8S 環境搭建 首先前期我們準備好三臺 Centos7 機器&#xff0c;配置如下&#xff1a; 主機名IP系統版本k8s-master192.168.41.141Centos7k8s-node1192.168.41.142Centos7k8s-node2192.168.41.143Centos7 前期準備 首先在三臺機器上都執行如下的命令 # 關閉防火墻…

Python讀取Word統計詞頻輸出到Excel

1.安裝依賴的包 "# 讀取docx\n", "!pip install python-docx\n", "!pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-docx\n", "# 中英文分詞\n", "!pip install jieba\n", "!pi…

postman測試后端增刪改查

目錄 一、本文介紹 二、準備工作 &#xff08;一&#xff09;新建測試 &#xff08;二&#xff09;默認url路徑查看方法 三、增刪改查 &#xff08;一&#xff09;查詢全部 &#xff08;二&#xff09;增加數據 &#xff08;三&#xff09;刪除數據 &#xff08;四&…

nginx反向代理流程

一、nginx反向代理流程 反向代理&#xff1a;使用代理服務器來接受internet上的連接請求&#xff0c;然后將請求轉發給內部網絡中的上游服務器&#xff0c;并將上游服務器得到的結果返回給請求連接的客戶端&#xff0c;代理服務器對外表現就是一個web服務器。Nginx就經常拿來做…

【內網穿透】如何實現在外web瀏覽器遠程訪問jupyter notebook服務器

文章目錄 前言1. Python環境安裝2. Jupyter 安裝3. 啟動Jupyter Notebook4. 遠程訪問4.1 安裝配置cpolar內網穿透4.2 創建隧道映射本地端口 5. 固定公網地址 前言 Jupyter Notebook&#xff0c;它是一個交互式的數據科學和計算環境&#xff0c;支持多種編程語言&#xff0c;如…

信也科技一面涼經

1.在項目經歷里挑一個詳細介紹一下 項目的應用場景 2.項目里用到多線程是怎么用的&#xff1f;回答&#xff1a;線程池 用通過 ThreadPoolExecutor 構造函數的方式創建的線程池 3.線程池有哪些重要參數&#xff1f;回答&#xff1a;核心線程數、最大線程數、阻塞隊列類型、…

【愛書不愛輸的程序猿】公網訪問本地搭建的WEB服務器之詳細教程

歡迎來到愛書不愛輸的程序猿的博客, 本博客致力于知識分享&#xff0c;與更多的人進行學習交流 本地電腦搭建Web服務器并用cpolar發布至公網訪問 前言1. 首先將PHPStudy、WordPress、cpolar下載到電腦2. 安裝PHPStudy3. 安裝cpolar&#xff0c;進入Web-UI界面4.安裝wordpress5.…

KU Leuven TU Berlin 推出“RobBERT”,一款荷蘭索塔 BERT

荷蘭語是大約24萬人的第一語言&#xff0c;也是近5萬人的第二語言&#xff0c;是繼英語和德語之后第三大日耳曼語言。來自比利時魯汶大學和柏林工業大學的一組研究人員最近推出了基于荷蘭RoBERTa的語言模型RobBERT。 谷歌的BERT&#xff08;來自Transformers的B idirectional …

C語言 常用工具型API --------system()

函數名&#xff1a; system&#xff08;&#xff09; 用 法&#xff1a; int system(char *command); 原理&#xff1a; 創建一個子進程去加載一個新程序執行&#xff0c;而Linux命令基本都是一個單獨的進程實現的&#xff0c;所以你所掌握的Linux命令越多&#xff0c;該函數…

AUTOSAR規范與ECU軟件開發(實踐篇)4.2 基于Matlab/Simulink的軟件組件開發

目錄 前言 1 、Matlab/Simulink與AUTOSAR基本概念的對應關系 2 、軟件組件內部行為建模方法

由淺入深學習Tapable

文章目錄 由淺入深學習TapableTapable是什么Tapable的Hook分類同步和異步的 使用Sync*同步類型鉤子基本使用bailLoopWaterfall Async*異步類型鉤子ParallelSeries 由淺入深學習Tapable webpack有兩個非常重要的類&#xff1a;Compiler和Compilation。他們通過注入插件的方式&a…

CentOS系統環境搭建(一)——Centos7更新

Centos7更新 更新 yum&#xff08;包括centos內核&#xff09; yum update執行后&#xff0c;系統將更新到centos 7.9。 從這一篇文章開始開始&#xff0c;我將開始在centos系統環境搭建&#x1f517;https://blog.csdn.net/weixin_43982359/category_12411496.html中開始對C…

【數據分析入門】Numpy進階

目錄 一、數據重塑1.1 透視1.2 透視表1.3 堆棧/反堆棧1.3 融合 二、迭代三、高級索引3.1 基礎選擇3.2 通過isin選擇3.3 通過Where選擇3.4 通過Query選擇3.5 設置/取消索引3.6 重置索引3.6.1 前向填充3.6.2 后向填充 3.7 多重索引 四、重復數據五、數據分組5.1 聚合5.2 轉換 六、…

回溯算法詳解

目錄 回溯算法詳解 回溯VS遞歸 回溯算法的實現過程 n個結點構造多本節要討論的是當給定 n&#xff08;n>0&#xff09;個結點時&#xff0c;可以構建多少種形態不同的樹。 回溯算法詳解 回溯算法&#xff0c;又稱為“試探法”。解決問題時&#xff0c;每進行一步&#…

主成分分析Python代碼

對于主成分分析詳細的介紹&#xff1a;主成分分析&#xff08;PCA&#xff09;原理詳解https://blog.csdn.net/zhongkelee/article/details/44064401 import numpy as np import pandas as pd標準PCA算法 def standeredPCA(data,N): #data:…

【golang】鏈表(List)

List實現了一個雙向鏈表&#xff0c;而Element則代表了鏈表中元素的結構。 可以把自己生成的Element類型值傳給鏈表嗎&#xff1f; 首先來看List的四種方法。 MoveBefore方法和MoveAfter方法&#xff0c;它們分別用于把給定的元素移動到另一個元素的前面和后面。 MoveToFro…

十種排序算法(附動圖)

排序算法 一、基本介紹 ? 排序算法比較基礎&#xff0c;但是設計到很多計算機科學的想法&#xff0c;如下&#xff1a; ? 1、比較和非比較的策略 ? 2、迭代和遞歸的實現 ? 3、分而治之思想 ? 4、最佳、最差、平均情況時間復雜度分析 ? 5、隨機算法 二、排序算法的分類 …

RabbitMq-1基礎概念

RabbitMq-----分布式中的一種通信手段 1. MQ的基本概念&#xff08;message queue,消息隊列&#xff09; mq:消息隊列&#xff0c;存儲消息的中間件 分布式系統通信的兩種方式&#xff1a;直接遠程調用&#xff0c;借助第三方完成間接通信 消息的發送方是生產者&#xff0c…