先建立一个节点的类
template <class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
,_right(nullptr)
,_key(key)
};
1、节点的插入
插入的值>当前的cur值,往右走;插入的值<当前的cur值,往左走;插入的值==当前的cur值,不需要插入;
//非递归写法
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(cur->key < key)
{
parent->_right= cur;
}
else
{
parent->_left = cur;
}
return true;
}
//递归写法
public:
bool Insert(const K& key)
{
return _InsertR(_root, key);
}
private:
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 _InsertR(Node*& root, const K& key)的Node*& root使用了引用,因此递归的时候,root->_right和root->_left都是下一层递归root的别名,当递归到root==nullptr时,就相当于root->_right == nullptr或root->_left == nullptr,创建新节点root = new Node(key),其实就已经把节点关系链接好了。
2、节点的删除
当要删除的节点有2个孩子时,要使用替换法,,替换的节点是右子树的最左节点或者左子树的最右节点,替换之后删除替换节点。替换节点要么只有1个孩子,要么没有孩子,可直接删除。
//非递归法
bool Erase(const K& key)
{
Node* parent =nullptr;
Node* cur =_root;
//让cur找到要删除的节点
while(cur)
{
if(_root->key < key)
{
parent=cur;
cur=cur->_right;
}
else if(_root->key > key)
{
parent=cur;
cur=cur->_left;
}
//相等的情况,也就是找到了要删除的节点
else
{
//只有一个或者0个孩子
if(cur->_left == nullptr)
{
//要删除的节点就是树的根
if(cur==_root)
{
_root=cur->_right;
}
else
{
if(cur==parent->left)
parent->_left = cur->_right;
else
parent->_right = cur->_right;
}
delete cur;
cur = nullptr;
}
else if(cur->_right == nullptr)
{
//要删除的节点就是树的根
if(cur==_root)
{
_root=cur->_left;
}
else
{
if(cur==parent->left)
parent->_left = cur->_left;
else
parent->_right = cur->_left;
}
delete cur;
cur = nullptr;
}
//删除的节点有2个孩子
else
{
Node* minParent =cur;
Node* min = cur->_right;
//找右子树的最左节点
while(min->_left)
{
minParent =min;
min=min->_left;
}
swap(cur->_key,min->_key);
//相当于无右孩子的情况
if(min==minParent->left)
minParent->_left = min->_left;
else
minParent->_right = min->_left;
delete min;
}
}
return true;
}
}
//递归删除
bool Erase(const K& key)
{
return _EraseR(_root, key);
}
bool _EraseR(Node*& root ,const K& key)
{
if(root==nullptr)
return false;
//因为Node*& root使用了引用,所以递归中,root->_right和root->_left都是递归到下一层的别名
if(root->_key < key)
return _EraseR(root->_right ,key);
else if(root->_key > key)
return _EraseR(root->_left ,key);
//找到了要删除的节点,此时root即为要删除的节点
else
{
Node* del = root;
//只有1个或者无孩子的情况
if(root->_left == nullptr)
root = root->_right;
else if(root->_right == nullptr)
root = root->_left;
//有两个孩子的情况
else
{
Node* min = root->_right;
while(min->_left)
{
min = min->_left;
}
swap(min->_key,del->_key);
//删除替换节点,此时相当于在右子树里再次递归删除
return _EraseR(root->_right ,key);
}
delete del;
return true;
}
}
3、中序遍历
public:
void Inorder()
{
_Inorder(_root);
cout<<endl;
}
private:
void _Inorder(Node* root)
{
if(root == nullptr)
return false;
_Inorder(root->_left);
cout<<root->_key<<"";
_Inorder(root->_right);
}
4、构造、析构和赋值
public:
//强制编译器生成默认构造
BSTree()=defalt;
//拷贝构造
BSTree(const BSTree<K>& t)
{
_root =_copy(t._root);
}
//析构函数
~BSTree()
{
_Destory(_root);
}
//赋值 t2=t1
BSTree<K>& operator=(BSTree<K> t)
{
swap(_root,t._root);
return *this
}
private:
Node* _copy(Node* root)
{
if(root==nullptr)
return nullptr;
Node* CopyRoot = new Node(root->key);
CopyRoot->_left = _copy(root->_left);
CopyRoot->_right = _copy(root->_right);
return CopyRoot;
}
void _Destory(Node*& root)
{
if(root==nullptr)
return;
_Destory(root->_left);
_Destory(root->_right);
delete root;
root = nullptr;
}