#ifndef CPP_BINARY_SEARCH_TREE_H
#define CPP_BINARY_SEARCH_TREE_H
#include <iostream>
#include <stack>
template <typename T>
class BinarySearchTree{
private:
struct Node{
T val;
Node *left, *right;
explicit Node(T &_val, Node *_left = nullptr, Node *_right = nullptr)
: val(_val), left(_left), right(_right) {}
};
Node *root;
private:
Node *copy(Node* ptr);
void destory();
public:
BinarySearchTree();
BinarySearchTree(const BinarySearchTree &rhs);
~BinarySearchTree();
BinarySearchTree &operator=(const BinarySearchTree &rhs);
bool operator==(const BinarySearchTree &rhs);
bool find(const T& val) const;
void insert(const T& val);
void delete(const T& val);
void print_tree(ostream &out = std::cout) const;
};
template <typename T>
BinarySearchTree<T>::BinarySearchTree(): root(nullptr) {}
template<typename T>
BinarySearchTree<T>::BinarySearchTree(const BinarySearchTree<T> &rhs):root(nullptr) {
root = copy(rhs.root);
}
template <typename T>
typename BinarySearchTree<T>::Node * // 必须要加typename 告诉编译器 node是一个类, 同时返回类型必须加 模板参数
BinarySearchTree<T>::copy(BinarySearchTree<T>::Node *ptr) { // 函数参数 可加, 可不加模板参数
/*
* 先序遍历ptr, 边遍历边拷贝,为遍历到的每个节点设置 相应拷贝节点的左右儿子
*/
if (!ptr)
return ptr;
std::stack<Node *> stk1, stk2;
ret = new Node(ptr->val);
stk1.push(ptr);
stk2.push(ret);
while (!stk1.empty()){
Node *cur = stk1.top();
stk1.pop();
Node *copy = stk2.top();
stk2.pop();
if (cur->right){
copy->right = new Node(cur->right->val);
stk1.push(cur->right);
stk2.push(copy->right);
}
if (cur->left) {
copy->left = new Node(cur->left->val);
stk1.push(cur->left);
stk2.push(copy->left);
}
}
return ret;
}
template <typename T>
BinarySearchTree<T>::~BinarySearchTree(){
destory();
}
template<typename T>
void BinarySearchTree<T>::destory() {
// 需要后序遍历
if (!root)
return;
stack<Node*> s1, s2;
s1.push(root);
while (!s1.empty()){
Node *cur = s1.top();
s1.pop();
s2.push(cur);
if (cur->left)
s1.push(cur->left);
if (cur->right)
s2.push(cur->right);
}
while (!s2.empty()){
Node *cur = s2.top();
s2.pop();
delete cur;
}
root = nullptr;
}
template<typename T>
BinarySearchTree<T> &BinarySearchTree<T>::operator=(const BinarySearchTree &rhs) {
if ((*this) == rhs)
return *this;
destory();
root = copy(rhs.root);
}
template<typename T>
bool BinarySearchTree<T>::operator==(const BinarySearchTree &rhs) {
return this->root == rhs.root;
}
template<typename T>
bool BinarySearchTree<T>::find(const T& val) const {
Node *cur = root;
while (cur){
if (val < cur->val)
cur = cur->left;
else if (val > cur->val)
cur = cur->right;
else
return true;
}
return false;
}
template<typename T>
void BinarySearchTree<T>::insert(const T& val) {
if (!root){
root = new Node(val);
return;
}
Node *cur = root;
while (cur){
if (val < cur->val){
if (!cur->left){
cur->left = new Node(val);
return;
}
cur = cur->left;
} else if (val > cur->val) {
if (!cur->right){
cur->right = new Node(val);
return;
}
cur = cur->right;
} else {
return;
}
}
}
template<typename T>
void BinarySearchTree<T>::delete(const T &val){
/*
* 被删除的节点有3种情况:
* 1) 没有孩子, 我们只需要直接将父节点中,指向要删除节点的指针置为 null
* 2) 只有一个孩子, 我们只需要更新父节点中,指向要删除节点的指针,让它指向要删除节点的那个唯一孩子就可以了。
* 3) 有两个孩子,
* 我们需要找到这个节点的右子树中的最小节点,把它替换到要删除的节点上。
* 然后再删除掉这个最小节点,因为最小节点肯定没有左子节点(如果有左子结点,那就不是最小节点了),
* 所以,我们可以应用上面两条规则来删除这个最小节点。比如图中的删除节点 18。
*/
Node *p = root;
Node *pp = nullptr; // 要删除节点的父亲节点
while (p && p->val != val){
pp = p;
if (val > p->val)
p = p->right;
else
p = p->left;
}
if (!p) // 没找到
return;
if (p->left && p->right){
Node *min_p = p->right, *min_pp = p; // 找右子树的最小节点。
while (min_p->left){
min_pp = min_p;
min_p = min_p->left;
}
p->val = min_p->val; // 将min_p的数据替换到p中
p = min_p; // 下面就变成了删除min_p了
pp = min_pp;
}
// 只有一个孩子或者没有孩子的情况
Node *child = p->left?p->left:p->right;
if (!pp)
root = child; // 删除的是根节点
else if (pp->left == p)
pp->left = child;
else
pp->right = child;
delete p;
}
#endif //CPP_BINARY_SEARCH_TREE_H
刷题(5)-二叉查找树(3)
最新推荐文章于 2023-03-11 21:59:26 发布