二插搜索树的插入
(1)树是空树,直接插入接口
(2)如果不是空树
需要找到插入位置,如果插入的值比当前节点的值要大,就去右子树找插入位置。如果插入的值比当前位置小,就去左子树找插入位置。如果和当前节点的值相等,就返回false,因为二叉搜索树不能存在两个相同的值。
普通写法:
bool Insert(const K& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
parent = cur;
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key > key)
{
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(key);
if (parent->_key < key)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
return true;
}
递归写法:
由于根节点是私有成员,在外部不能访问,因此需要一个成员函数去调用,这也是C++常用的处理方法。
这里使用的是节点的引用,就可以在递归途中直接修改节点
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
bool _InsertR(Node*& root, const K& key)
{
if (root == nullptr)
{
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;
}
}
二叉搜索树的查找
如果要查找的值比当前节点的值要大,就去右子树查找,如果比当前节点的值要小,就去左子树查找,如果等于当前节点的值,就返回true,用这个方法向下找,如果没有找到就返回false
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 FindR(const K& key)
{
return _FindR(_root, key);
}
bool _FindR(Node* root,const K& key)
{
if (root == nullptr)
{
return false;
}
if (root->_key < key)
{
_FindR(root->_right, key);
}
else if (root->_key > key)
{
_FindR(root->_left, key);
}
else
{
return true;
}
}
二叉搜索树的删除
二叉搜索树的删除需要分类讨论
首先是要阐述的节点是否有双亲,其次是要删除的节点是双亲的左孩子还是右孩子,并且要删除的节点有没有孩子,是只有左孩子还是只有右孩子,或者是有两个孩子
(1)要删除的节点有双亲
(a)要删除的节点是双亲的左孩子
【1】要删除的节点没有孩子:直接删除这个节点就可以
【2】 要删除的节点只有左孩子:此时需要让这个节点的父节点指向这个节点的左孩子,再删除这个节点
【3】要删除的节点只有右孩子:此时需要让这个节点的父节点指向这个节点的右孩子,再删除这个节点
【4】要删除的节点有两个孩子
这里需要找一个替代节点,可以使删除节点左子树的最大节点(左子树的最右侧的节点),或者要删除及诶单左子树的最小节点(左子树的最左侧节点) ,把这个节点的值赋值给要删除的节点,再删除掉这个替代节点即可。
(b) 要删除的节点是双亲的左孩子
与左孩子同理
(2)要删除的节点没有双亲
(a)要删除节点没有孩子:直接删除即可
(b)要删除的节点只有左孩子:让左孩子直接当根节点,删除这个节点即可
(c)要删除的节点只有右孩子:让这个节点当根节点即可
(d)要删除的节点有两个孩子
找到右子树的最小节点,替换之后删除即可
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
{
if (cur->_left == nullptr)
{
if (cur == _root)
{
_root = cur->_right;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
}
}
else if (cur->_right == nullptr)
{
if (cur == _root)
{
_root = cur->_right;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
}
else
{
Node* parent = cur;
Node* subLeft = cur;
while (subLeft->_left)
{
parent = subLeft;
subLeft = subLeft->_left;
}
swap(subLeft->_key, cur->_key);
if (subLeft == parent->_left)
{
parent->_left = subLeft->_right;
}
else
{
parent->_left = subLeft->_right;
}
}
return true;
}
}
return false;
}
递归写法:
bool EraseR(const K& key)
{
return _EnerseR(_root, key);
}
bool _EnerseR(Node*& root, const K& key)
{
if (root == nullptr)
{
return false;
}
if (root->_key < key)
{
_EnerseR(root->_right, key);
}
else if (root->_key > key)
{
_EnerseR(root->_left, key);
}
else
{
if (root->_left == nullptr)
{
Node* del = root;
root = root->_right;
delete del;
return true;
}
else if (root->_right == nullptr)
{
Node* del = root;
root = root->_left;
delete del;
return true;
}
else
{
Node* subLeft = root;
while (subLeft->_left)
{
subLeft = subLeft->_left;
}
swap(subLeft->_key, root->_key);
return _EnerseR(root->_right, key);
}
}
}
整体实现
#pragma once
#include<iostream>>
using namespace std;
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
,_right(nullptr)
,_key(key)
{}
};
template<class K>
class BSTree
{
typedef BSTreeNode<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)
{
parent = cur;
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key > key)
{
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
{
if (cur->_left == nullptr)
{
if (cur == _root)
{
_root = cur->_right;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
}
}
else if (cur->_right == nullptr)
{
if (cur == _root)
{
_root = cur->_right;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
}
else
{
Node* parent = cur;
Node* subLeft = cur;
while (subLeft->_left)
{
parent = subLeft;
subLeft = subLeft->_left;
}
swap(subLeft->_key, cur->_key);
if (subLeft == parent->_left)
{
parent->_left = subLeft->_right;
}
else
{
parent->_left = subLeft->_right;
}
}
return true;
}
}
return false;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool FindR(const K& key)
{
return _FindR(_root, key);
}
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
bool EraseR(const K& key)
{
return _EnerseR(_root, key);
}
private:
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
bool _FindR(Node* root,const K& key)
{
if (root == nullptr)
{
return false;
}
if (root->_key < key)
{
_FindR(root->_right, key);
}
else if (root->_key > key)
{
_FindR(root->_left, key);
}
else
{
return true;
}
}
bool _InsertR(Node*& root, const K& key)
{
if (root == nullptr)
{
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 _EnerseR(Node*& root, const K& key)
{
if (root == nullptr)
{
return false;
}
if (root->_key < key)
{
_EnerseR(root->_right, key);
}
else if (root->_key > key)
{
_EnerseR(root->_left, key);
}
else
{
if (root->_left == nullptr)
{
Node* del = root;
root = root->_right;
delete del;
return true;
}
else if (root->_right == nullptr)
{
Node* del = root;
root = root->_left;
delete del;
return true;
}
else
{
Node* subLeft = root;
while (subLeft->_left)
{
subLeft = subLeft->_left;
}
swap(subLeft->_key, root->_key);
return _EnerseR(root->_right, key);
}
}
}
private:
Node* _root = nullptr;
};