C++ 詳解數(shù)據(jù)結(jié)構(gòu)中的搜索二叉樹(shù)
定義
搜索二叉樹(shù),也稱(chēng)有序二叉樹(shù),排序二叉樹(shù),是指一棵空樹(shù)或者具有下列性質(zhì)的二叉樹(shù):
1、若任意節(jié)點(diǎn)的左子樹(shù)不空,則左子樹(shù)上的所有節(jié)點(diǎn)的值均小于它的根節(jié)點(diǎn)的值
2、若任意節(jié)點(diǎn)的右子樹(shù)不空,則右子樹(shù)上的所有節(jié)點(diǎn)的值均大于它的根節(jié)點(diǎn)的值
3、任意節(jié)點(diǎn)的左右子樹(shù)也稱(chēng)為二叉查找樹(shù)。
4、沒(méi)有鍵值相等的節(jié)點(diǎn)。
5、搜索二叉樹(shù)中序遍歷為有序數(shù)組。
結(jié)構(gòu)代碼實(shí)現(xiàn)
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(left)
,_right(right)
,_key(key)
{}
};查找某個(gè)元素
在搜索二叉樹(shù)b中查找x的過(guò)程
- 若樹(shù)是一個(gè)空樹(shù),則搜索失敗,否則:
- 若x等于b的根節(jié)點(diǎn)的鍵值,則查找成功;否則:
- 若x小于b的根節(jié)點(diǎn)的鍵值,則搜索左子樹(shù);否則:
- 若x大于b的根節(jié)點(diǎn)的鍵值,則搜索右子樹(shù)。

非遞歸實(shí)現(xiàn)
typrdef BSTreeNode<K> Node;
?
Node* 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 cur;
}
return nullptr;
}遞歸實(shí)現(xiàn)
typrdef BSTreeNode<K> Node;
?
Node* _findr(Node* root,const K& key)
{
if(root==nullptr)
{
return nullptr;
}
if(root->_key<key)
{
return _findr(root->_right);
}
else if(root->_key>key)
{
return _findr(root->_left);
}
else
return root;
}構(gòu)造搜索二叉樹(shù)
- 若樹(shù)為空樹(shù),則直接插入;否則
- 若插入值大于根節(jié)點(diǎn)的鍵值,則插入到右子樹(shù)中,以此遞歸;否則
- 若插入值小于根節(jié)點(diǎn)的鍵值,則插入到左子樹(shù)中

非遞歸實(shí)現(xiàn):
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;
}遞歸實(shí)現(xiàn):
bool _insertR(Node* &root,const K&key)
{
if(root==NULL)
{
root=new Node(key);
return true;
}
if(root->_key<key)
return _insertR(root->_right,key);
else if(root->_key>key)
return _insertR(root->_left,key);
else
return false;
}往搜索二叉樹(shù)中插入元素
向一個(gè)二叉搜索樹(shù)b中插入一個(gè)節(jié)點(diǎn)s的算法,過(guò)程為:
- 若b是空樹(shù),則將s所指結(jié)點(diǎn)作為根節(jié)點(diǎn)插入,否則:
- 若s->data等于b的根節(jié)點(diǎn)的數(shù)據(jù)域之值,則返回,否則:
- 若s->data小于b的根節(jié)點(diǎn)的數(shù)據(jù)域之值,則把s所指節(jié)點(diǎn)插入到左子樹(shù)中,否則:
- 把s所指節(jié)點(diǎn)插入到右子樹(shù)中。(新插入節(jié)點(diǎn)總是葉子節(jié)點(diǎn))

搜索二叉樹(shù)刪除節(jié)點(diǎn)
重難點(diǎn)
二叉搜索樹(shù)的結(jié)點(diǎn)刪除比插入較為復(fù)雜,總體來(lái)說(shuō),結(jié)點(diǎn)的刪除可歸結(jié)為三種情況:
- 如果結(jié)點(diǎn)z沒(méi)有孩子節(jié)點(diǎn),那么只需簡(jiǎn)單地將其刪除,并修改父節(jié)點(diǎn),用NULL來(lái)替換z;
- 如果結(jié)點(diǎn)z只有一個(gè)孩子,那么將這個(gè)孩子節(jié)點(diǎn)提升到z的位置,并修改z的父節(jié)點(diǎn),用z的孩子替換z;
- 如果結(jié)點(diǎn)z有2個(gè)孩子,那么查找z的后繼y,此外后繼一定在z的右子樹(shù)中,然后讓y替換z

非遞歸實(shí)現(xiàn)
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
{
//找到了,開(kāi)始刪除
if(cur->_left==nullptr)
{
if(cur==_root)
{
_root=cur->_right;
}
else
{
if(parent->_left==cur)
{
parent->_left=cur->_right;
}
else
{
parent->_right=cur->_right;
}
}
delete cur;
}
else if(cur->_right==nullptr)
{
if(cur==_root)
{
_root=cur->_left;
}
else
{
if(parent->_left==cur)
{
parent->_left=cur->_left;
}
else
{
parent->_right=cur->_right;
}
}
}
else //左右都不為空
{
Node* minRight=cur->_right;
while(minRight->_left)
{
minRight=minRight->_left;
}
k min = minRight->_key;
this->Erase(min);
cur->_key=min;
}
return true;
}
}
return false;
}遞歸實(shí)現(xiàn)
// 如果樹(shù)中不存在key,返回false
// 存在,刪除后,返回true
bool _EraseR(Node*& root, const K& key)
{
if(root==nullptr)
return false;
if(root->_key<key)
return _EraseR(root->_right,key);
else if(root->_key>key)
return _EraseR(root->_left,key);
else
{
//找到了,root就是要?jiǎng)h除的節(jié)點(diǎn)
if(root->_left == nullptr)
{
Node* del=root;
root=root->_right;
delete del;
}
else if(root->_right==nullptr)
{
Node* del = root;
root=root->_left;
delete del;
}
else
{
Node* minRight=root->_right;
while(minRight->_left)
{
minRight=minRight->_left;
}
K min=minRight->_key;
//轉(zhuǎn)化為root的右子樹(shù)刪除min
_EraseR(root->_right,min);
root->_key=min;
}
return true;
}
}到此這篇關(guān)于C++ 詳解數(shù)據(jù)結(jié)構(gòu)中的搜索二叉樹(shù)的文章就介紹到這了,更多相關(guān)C++ 搜索二叉樹(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)控制臺(tái)掃雷小游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)控制臺(tái)掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
C語(yǔ)言指針學(xué)習(xí)經(jīng)驗(yàn)總結(jié)淺談
指針是C語(yǔ)言的難點(diǎn)和重點(diǎn),但指針也是C語(yǔ)言的靈魂 。2013-03-03
C++11新特性之四種類(lèi)型轉(zhuǎn)換cast說(shuō)明
類(lèi)型轉(zhuǎn)換是項(xiàng)目中常使用的一種語(yǔ)法規(guī)則,幾乎每個(gè)編程語(yǔ)言都不可避免的涉及到這方面,下面這篇文章主要給大家介紹了關(guān)于C++11新特性之四種類(lèi)型轉(zhuǎn)換cast說(shuō)明的相關(guān)資料,需要的朋友可以參考下2023-02-02
C語(yǔ)言strlen和sizeof在數(shù)組中的使用詳解
對(duì)于 strlen 和 sizeof,相信不少程序員會(huì)混淆其功能。雖然從表面上看它們都可以求字符串的長(zhǎng)度,但二者卻存在著許多不同之處及本質(zhì)區(qū)別2021-10-10
C/C++?Qt?數(shù)據(jù)庫(kù)QSql增刪改查組件應(yīng)用教程
Qt?SQL模塊是Qt中用來(lái)操作數(shù)據(jù)庫(kù)的類(lèi),該類(lèi)封裝了各種SQL數(shù)據(jù)庫(kù)接口,可以很方便的鏈接并使用。本文主要介紹了Qt數(shù)據(jù)庫(kù)QSql增刪改查組件的應(yīng)用教程,感興趣的同學(xué)可以學(xué)習(xí)一下2021-12-12
C語(yǔ)言驅(qū)動(dòng)開(kāi)發(fā)之通過(guò)ReadFile與內(nèi)核層通信
驅(qū)動(dòng)與應(yīng)用程序的通信是非常有必要的,內(nèi)核中執(zhí)行代碼后需要將其動(dòng)態(tài)顯示給應(yīng)用層。為了實(shí)現(xiàn)內(nèi)核與應(yīng)用層數(shù)據(jù)交互則必須有通信的方法,微軟為我們提供了三種通信方式,本文先來(lái)介紹通過(guò)ReadFile系列函數(shù)實(shí)現(xiàn)的通信模式2022-09-09
C++實(shí)現(xiàn)掃雷程序開(kāi)發(fā)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)掃雷程序開(kāi)發(fā),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
C語(yǔ)言驅(qū)動(dòng)開(kāi)發(fā)之內(nèi)核通過(guò)PEB獲取進(jìn)程參數(shù)
PEB結(jié)構(gòu)(Process Envirorment Block Structure)其中文名是進(jìn)程環(huán)境塊信息。本文將通過(guò)PEB實(shí)現(xiàn)獲取進(jìn)程參數(shù),感興趣的小伙伴可以了解一下2022-10-10

