https://mp.weixin.qq.com/s?__biz=MzU0ODMyNDk0Mw==&mid=2247495540&idx=1&sn=214e962041b5c8e9a70bd4059371ad05&chksm=fb427c54cc35f542e1b3ef7c9fd6ed5b6267843e12e0d93d282c2bd2fdac59edc6bec83fd9a1&scene=27
1 普通二叉搜索树
template <typename T>
struct BSTNode
{
struct BSTNode<T> *left;
struct BSTNode<T> *right;
T _key;
BSTNode(const T& key): _key(key), left(nullptr), right(nullptr)
{
}
};
1.1 查找
步骤如下:
- 如果当前节点为空,则搜索失败。
- 否则,如果当前节点的值等于要查找的值,则直接返回。
- 否则,如果要查找的值比当前节点小,就往当前节点的左子树找。如果要查找的值比当前节点值大,就往当前节点的右子树找。
1.1.1 迭代查找
template <typename T>
BSTNode<T>* find(BSTNode<T>* root, const T& key)
{
BSTNode<T>* ret = root;
while(ret && key != ret->_key) {
if(key < ret->_key){
ret = ret->left;
}
else{
ret = ret->right;
}
}
return ret;
}
1.1.2 递归查找
template<typename T>
BSTNode<T>* iterfind(BSTNode<T>* root, const T& key)
{
if(nullptr == root) {
return nullptr;
}
if(key == root->_key) {
return root;
}
if(key > root->_key) {
return iterfind(root->right, key);
}
else {
return iterfind(root->left);
}
}
1.2 插入
1.2.1 迭代混入
总体思路:
- 从根节点开始,根据待插入节点的值与当前节点的值比较,决定向左子树还是右子树移动。
- 使用一个指针遍历二叉树,直到找到空位置插入新节点。
template<typename T>
bool insert(BSTNode<T>* root, const T& key)
{
if(nullptr == root) {
return false;
}
BSTNode<T>* ptr = root;
while(ptr) {
if(key > ptr->_key) {
if(nullptr == ptr->right){
ptr->right = new BSTNode<T>(key);
return true;
}
else{
ptr = ptr->right;
}
}
else if(key < ptr->_key){
if(nullptr == ptr->left){
ptr->left = new BSTNode<T>(key);
return true;
}
else{
ptr = ptr->left;
}
}
else{
return true;
}
}
return false;
}
1.2.2 递归插入
template <typename T>
bool insert(BSTNode<T>* root, const T& key)
{
if(nullptr == root) {
return false;
}
if(key == root->_key) {
return true;
}
if(key > root->_key) {
insert(root->right, key);
}
else{
insert(root->left, key);
}
}
1.3 删除
删除比较麻烦要考虑三种情况:
- 要删除的是叶子节点:直接删除,再将父节点指向叶子节点的指针置为
NULL
. - 要删除的节点只有一个子节点:将其父节点指向待删除节点的子节点
- 要删除的节点有左右节点:用另一个节点替代被删除节点,如左边树的最大元素,或者右边树的最小元素。而且替代节点是一定没有两个子节点的,所以可以将问题简单化
1.3.1 迭代删除
template<typename T>
bool deletenode(BSTNode<T>* root, const T& key)
{
if(nullptr == root) {
return false;
}
BSTNode* cur = root;
BSTNode* par = nullptr;
while(cur)
{
if(key == cur->_key) {
if(nullptr == cur->left && nullptr == cur->right)
{
if(cur != root) {
if(par->left == cur) {
par->left = nullptr;
}
else {
par->right = nullptr;
}
}
delete cur;
cur = nullptr;
}
else if(nullptr == cur->left)
{
if(cur != root) {
if(par->left == cur) { // 确认是父亲的左孩子还是右孩子
par->left = cur->right;
}
else {
par->right = cur->right;
}
}
else { // 用新的节点替换root
root = root->right;
}
delete cur;
cur = nullptr;
}
else if(nullptr == cur->right)
{
if(cur != root) {
if(par->left == cur) {
par->left = cur->left;
}
else {
par->right = cur->left;
}
}
else {
root = root->left;
}
delete cur;
cur = nullptr;
}
else//找右孩子最大
{
BSTnode* min = cur->right;
BSTNode* minpar = nullptr;
while(min->left)
{
minpar = min;
min = min->left;
}
swap(cur->_key, min->_key);
if(minpar->left == min) {
minpar->left = nullptr;
}
else {
minpar->right = nullptr;
}
delete min;
min = null;
}
return true;
}
if(key < cur->_key) {
par = cur;
cur = cur->left;
continue;
}
else {
par = cur;
cur = cur->right;
continue;
}
}
return false;
}
1.3.2 递归删除
bool _EraseR(Node*& root, const K& key)
{
Node* del = root;
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
{
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(root->_key, min->_key);
//交换后结构改变不是搜索二叉树了,规定范围在右树(因为是右树最左节点替换)再递归
return _EraseR(root->_right, key);
}
delete del;
return true;
}
}