搜索树BinarySearchTree

定义

二叉搜索树(Binary Search Tree), 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

组成

template <class K>
struct BSNode
{
BSNode<K>* _left;
BSNode<K>* _right;
K _key;

BSNode<K>(const K& key)
:_left(NULL)
,_right(NULL)
,_key(key)
{}
};

左右孩子_left,_right,用来比较大小的key值

主要实现操作

插入

当前节点为空,则直接给_root根节点插入。 
比根节点,插入到根节点的右树上。 
比根节点,插入到根节点的左树上。

插入代码

bool Insert(const K& key)
{
if (NULL == _root)
{
_root = new Node(key);
return true;
}

Node* parent = NULL;
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;
}
}

if (parent->_key < key)
{
parent->_right = new Node(key);
}
else
{
parent->_left = new Node(key);
}
return true;
}

删除

递归版

比当前节点大,到当前节点的右树上查找并删除; 
比当前节点大,到当前节点的右树上查找并删除; 
当前节点就是需要删除的节点 
1.找到当前节点右子树的最左节点,与要被删除节点交换,从当前节点的父节点继续递归删除。

bool _RemoveR(Node*& cur, const K& key)
{
if (NULL == cur){
return false;
}

if (cur->_key < key){
return _RemoveR(cur->_right, key);
}
else if (cur->_key > key){
return _RemoveR(cur->_left, key);
}
else{
//找到为key的节点cur
Node* del = cur;
if (NULL == cur->_left){
cur = cur->_right;
}
else if (NULL == cur->_right){
cur = cur->_left;
}
else
{
Node* tmp = cur;
Node* parent = cur->_right;
cur = cur->_left;
while (cur)
{
parent = cur;
cur = cur->_left;
}
//parent现在是以被删除节点为根,右子树的最左节点
swap(parent->_key, tmp->_key);

return _RemoveR(parent, key);
}
delete del;
return true;
}
return false;
}
非递归版

找到需要删除的节点,进行如下判断 
1.del(需要删除的节点)的左孩子为空时,判断del是否为根节点,不是根节点,再判断是parent的左孩子还是右孩子,判断好后进行删除 
2.del的右孩子为空时与左类似 
3.del的左右孩子都不为空,使用替换法

    bool Rmove(const K& key)
{
if (NULL == _root){return true;}

Node* cur = _root;
Node* parent = NULL;
Node* del = NULL;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}

else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}

else
{
if (NULL == cur->_left) //删除节点的左孩子为空
{
if (NULL == parent) //当前节点为根节点
{
_root = cur->_right;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_right; //让父节点的左孩子指向当前节点的右孩子
}

else if (cur == parent->_right)
{
parent->_right = cur->_right; //让父节点的右孩子指向当前节点的右孩子
}
}
del = cur;
}


else if (NULL == cur->_right) //删除节点的右孩子为空
{
if (NULL == parent) //当前节点为根节点
{
_root = cur->_left;
}
else
{
if (cur == parent->_left) //parent的左孩子是cur且cur的右孩子为空
{
parent->_left = cur->_left;
}

if (cur == parent->_right)
{
parent->_right = cur->_left;//parent的右孩子是cur且cur的右孩子为空
}
}
delete cur;
}

else //删除节点的左右孩子都不为空
{
//利用替换法,将当前节点视为根节点,找当前节点右子树最左节点,与要删除的节点做替换
Node* tmp = cur;
Node* subNode = cur->_right;//右子树肯定不为空
while (subNode->_left)
{
tmp = subNode;
subNode = subNode->_left;
}
//找到右子树的最左节点tmp;
swap(cur->_key, subNode->_key);//交换数据

//分两种情况
if (tmp->_left == subNode) //tmp的左为替换节点
{
tmp->_left = subNode->_right;
}

else if(tmp->_right == subNode)
{
tmp->_right = subNode->_right;
}
del = subNode;
}
delete del;
return true;
}
}
return false;
}

完整实现

BSTree.h

#ifndef __BSTREE_H__
#define __BSTREE_H__

#include <iostream>

using namespace std;

template <class K>
struct BSNode
{
BSNode<K>* _left;
BSNode<K>* _right;
K _key;

BSNode<K>(const K& key)
:_left(NULL)
,_right(NULL)
,_key(key)
{}
};

template <class K>
class BSTree
{
typedef BSNode<K> Node;
public:
BSTree()
:_root(NULL)
{}
/*BSTree(const)
{}*/

bool Insert(const K& key)
{
if (NULL == _root)
{
_root = new Node(key);
return true;
}

Node* parent = NULL;
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;
}
}

if (parent->_key < key)
{
parent->_right = new Node(key);
}
else
{
parent->_left = new Node(key);
}
return true;
}

bool Rmove(const K& key)
{
if (NULL == _root){return true;}

Node* cur = _root;
Node* parent = NULL;
Node* del = NULL;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}

else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}

else
{
if (NULL == cur->_left) //删除节点的左孩子为空
{
if (NULL == parent) //当前节点为根节点
{
_root = cur->_right;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_right; //让父节点的左孩子指向当前节点的右孩子
}

else if (cur == parent->_right)
{
parent->_right = cur->_right; //让父节点的右孩子指向当前节点的右孩子
}
}
del = cur;
}


else if (NULL == cur->_right) //删除节点的右孩子为空
{
if (NULL == parent) //当前节点为根节点
{
_root = cur->_left;
}
else
{
if (cur == parent->_left) //parent的左孩子是cur且cur的右孩子为空
{
parent->_left = cur->_left;
}

if (cur == parent->_right)
{
parent->_right = cur->_left;//parent的右孩子是cur且cur的右孩子为空
}
}
delete cur;
}

else //删除节点的左右孩子都不为空
{
//利用替换法,将当前节点视为根节点,找当前节点右子树最左节点,与要删除的节点做替换
Node* tmp = cur;
Node* subNode = cur->_right;//右子树肯定不为空
while (subNode->_left)
{
tmp = subNode;
subNode = subNode->_left;
}
//找到右子树的最左节点tmp;
swap(cur->_key, subNode->_key);//交换数据

//分两种情况
if (tmp->_left == subNode) //tmp的左为替换节点
{
tmp->_left = subNode->_right;
}

else if(tmp->_right == subNode)
{
tmp->_right = subNode->_right;
}
del = subNode;
}
delete del;
return true;
}
}
return false;
}

void InOder()
{
_InOder(_root);
cout<<endl;
}

bool RmoveR(const K& key)
{
return _RemoveR(_root, key);
}
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
bool Find(const K& key)
{
if (_root == NULL)
return false;

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 FindR(const K& key)
{
return _FindR(_root, key);
}
~BSTree()
{
_Destory(_root);
}
protected:
bool _RemoveR(Node*& cur, const K& key)
{
if (NULL == cur){
return false;
}

if (cur->_key < key){
return _RemoveR(cur->_right, key);
}
else if (cur->_key > key){
return _RemoveR(cur->_left, key);
}
else{
//找到为key的节点cur
Node* del = cur;
if (NULL == cur->_left){
cur = cur->_right;
}
else if (NULL == cur->_right){
cur = cur->_left;
}
else
{
Node* tmp = cur;
Node* parent = cur->_right;
cur = cur->_left;
while (cur)
{
parent = cur;
cur = cur->_left;
}
//parent现在是以被删除节点为根,右子树的最左节点
swap(parent->_key, tmp->_key);

return _RemoveR(parent, key);
}
delete del;
return true;
}
return false;
}
bool _InsertR(Node*& root, const K& key)
{
if (NULL == root)
{
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;
}
bool _FindR(Node* root,const K& key)
{
if (NULL == root){return false;}

if (root->_key < key){
return _FindR(root->_right, key);
}
else if (root->_key > key){
return _FindR(root->_left, key);
}
else {
return true;
}

return false;
}
void _Destory(Node* root)
{
if (NULL == root){return;}

_Destory(root->_left);
_Destory(root->_right);

delete root;
}

void _InOder(Node* root)
{
if (NULL == root){return;}

_InOder(root->_left);
cout<<root->_key<<" ";
_InOder(root->_right);
}
protected:
Node* _root;
};
#endif //__BSTREE_H__
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值