C++之二叉排序树(二叉搜索树)的实现(4)---《那些奇怪的算法》

二叉排序树的实现难点主要集中在删除、求解节点的前驱和节点的后继这三个步骤,注意,求解节点的前驱和后继部分指的是中序遍历中的节点的前驱和后继啦,

1)二叉排序树针对删除所面临的三种情况:

1)当前节点无左右子树,直接删除该节点,修改父节点的对应指针;
2)节点p有左子树(右子树),则把p的左子树(右子树)接到p的父节点上面,并删除p节点;
3)左右子树同时存在:

  • 找到节点p的中序直接节点s,把节点s的数据转移到节点p,然后删除节点s,由于节点s为p的左子树中最右边的节点,因而s无右子树,删除节点s可以归类为2);
    这里写图片描述
  • 找到节点p的中序直接后继节点s,并把节点s的数据转移到节点p,然后删除节点s,由于节点s为p的右子树中最左边的节点,因而s无左子树,删除节点可以归类到情况2);
    这里写图片描述
  • 找到p的直接前驱s,将p的左子树接到父节点上面,将p的右子树接到节点s的右子树上,然后删除节点p。
    这里写图片描述

算法导轮中列举出来的几种主要情况:
这里写图片描述

2)二叉搜索树中求取前驱:

1)当前节点存在左节点;
2)当前节点是父节点的左节点;
3)当前节点是父节点的右节点。

3)二叉排序树中求取后继:

1)当前节点存在右节点;
2)当前节点是父节点的左节点;
3)当前节点是父节点的右节点。

二叉排序树的构造:
这里写图片描述
这是我们所设计的实现代码:

#include <iostream>
#include <string>
#include <stack>
using namespace std;

class BSTNode{
public:
    int key;
    BSTNode* left;
    BSTNode* right;
    BSTNode* parent;
    BSTNode(){
        key = 0;
        left = right = parent = NULL;
    }
    BSTNode(int key, BSTNode* l=NULL, BSTNode* r=NULL, BSTNode* p=NULL) :
        key(key), left(l), right(r), parent(p){

    }
};

void BSTree_insert(BSTNode* root, BSTNode *node){
    BSTNode *temp=NULL;
    while (root != NULL){
        temp = root;
        if (node->key < temp->key){
            root = root->left;
        }
        else{
            root = root->right;
        }
    }
    node->parent = temp;
    if (temp == NULL){
        root = node;
    }
    else if (node->key < temp->key){
        temp->left = node;
    }
    else{
        temp->right = node;
    }
}
BSTNode* BSTree_Min(BSTNode* root){
    BSTNode* temp=NULL;
    //***********
    while (root != NULL){
        temp=root;
        root = root->left;
    }
    return temp;
}
BSTNode* BSTree_Max(BSTNode* root){
    BSTNode* temp=NULL;
    //***********
    while (root != NULL){
        temp=root;
        root = root->right;
    }
    return temp;
}
//中序遍历中求取节点的后继节点
BSTNode* BSTree_suc(BSTNode* node){
    if (node->right) return BSTree_Max(node->right);
    //如果节点没有右节点,那么现在也要考虑两种情况:
    //1)节点是父节点的左节点
    //2)节点是父节点的右节点
    BSTNode* parent = node->parent;
    while (node != NULL&&node == parent->right){
        node = parent;
        parent = parent->parent;
    }
    return parent;
}
//中序遍历中求取节点的前驱节点
BSTNode* BSTree_predecess(BSTNode* node){
    //如果节点node有左节点,那么其前驱是其左节点中值最大的;
    if (node->left) return BSTree_Max(node->left);
    //如果节点node没有左节点,现在需要考虑两种情况,
    //1)节点是父节点的右节点;
    //2)节点是其父节点的左节点;
    BSTNode* parent = node->parent;
    while (parent != NULL&&node == parent->left){
        node = parent;
        parent = parent->parent;
    }
    return parent;
}

void BSTree_remove_pre(BSTNode* node){
    BSTNode* temp = NULL;
    //当前节点右子树为空
    if (!node->right){
        temp = node;
        //当前节点的父节点不为空
        if (node->parent){
            //当前节点是父节点的左节点
            if (node->parent->left == node){
                node->parent->left = node->left;
            }
            //当前节点是父节点的右边节点
            else{
                node->parent->right = node->left;
            }
        }
        else{
            node = node->left;
        }
        delete temp;
    }
    else if(!node->left){
        temp = node;
        //当前节点左子树为空,右子树不空空
        if (node->parent){
            //当前节点是父节点的左节点
            if (node->parent->left == node){
                node->parent->left = node->right;
            }
            //当前节点是父节点的右节点
            else{
                node->parent->right = node->right;
            }
        }
        else{
            node = node->right;
        }
        delete temp;
    }
    else{
        BSTNode* sucNode = NULL;
        temp = node;
        //采用这种方法是为了避免所有都使用其前驱替换,考虑一下删除以10为前驱的节点的时候,形成的结构是怎样的???很难吧!
        sucNode = node->left;
        while (sucNode->right){
            temp = sucNode;
            sucNode=sucNode->right;
        }
        node->key = sucNode->key;
        if (temp != node){
            temp->right = sucNode->left;
        }
        else{
            temp->left = sucNode->left;
        }
        delete sucNode;
    }
}
void BSTree_remove_post(BSTNode* node){
    BSTNode* temp = NULL;
    if (!node->right){
        temp = node;
        if (node->parent){
            if (node->parent->left == node){
                node->parent->left = node->left;
            }
            else{
                node->parent->right = node->left;
            }
        }
        else{
            node = node->left;
        }
        delete temp;
    }
    else if (!node->left){
        temp = node;
        if (node->parent){
            if (node->parent->left == node){
                node->parent->left = node->right;
            }
            else{
                node->parent->right = node->right;
            }
        }
        else{
            node = node->right;
        }
        delete temp;
    }
    else{
        BSTNode* sucNode = NULL;
        temp = node;
        sucNode = node->right;
        while (sucNode->left){
            temp = sucNode;
            sucNode = sucNode->left;
        }
        node->key = sucNode->key;
        if (temp != node){
            temp->left = sucNode->right;
        }
        else{
            temp->right = sucNode->right;
        }
        delete sucNode;
    }
}
void BSTree_remove_plus(BSTNode* node){
    BSTNode* temp = NULL;
    if (!node->right){
        temp = node;
        node = node->left;
        delete temp;
    }
    else if (!node->left){
        temp = node;
        node = node->right;
        delete temp;
    }
    else{
        BSTNode* s = NULL;
        temp = node;
        s = node->left;
        while (s->right){
            s = s->right;
        }
        s->right = node->right;
        node = node->left;
        delete temp;
    }
}
BSTNode* BSTree_remove_Non_standard( BSTNode* node){
    BSTNode* x;
    BSTNode* y;
    if ((node->left == NULL || node->right == NULL)){
        y = node;
    }
    else{
        y = BSTree_suc(node);
    }
    if (y->left != NULL){
        x = y->left;
    }
    else{
        x = y->right;
    }
    if (x != NULL){
        x->parent = y->parent;
    }
    if (y->parent == NULL){

    }
    else if (y == y->parent->left){
        y->parent->left = x;
    }
    else{
        y->parent->right = x;
    }

    if (y != node){
        node->key = y->key;
    }
    return y;

}
BSTNode* BSTree_search(BSTNode* node, int val){
    if (node == NULL || val == node->key){
        return node;
    }
    if (val < node->key){
        BSTree_search(node->left, val);
    }
    else{
        BSTree_search(node->right, val);
    }
}
void preorder_show(BSTNode* root){
    stack<BSTNode*> s;
    while (root != NULL || !s.empty()){
        while (root != NULL){
            cout << root->key << " ";
            s.push(root);
            root = root->left;
        }
        if (!s.empty()){
            root = s.top();
            s.pop();
            root = root->right;
        }
    }
    cout << endl;
}
void inorder_show(BSTNode* root){
    stack<BSTNode*> s;
    while (root != NULL||!s.empty()){
        while (root != NULL){
            s.push(root);
            root = root->left;
        }
        if (!s.empty()){
            root = s.top();
            cout << root->key << " ";
            s.pop();
            root = root->right;
        }
    }
    cout << endl;
}
void postorder_show(BSTNode* root){
    stack<BSTNode*> s;
    BSTNode* cur = NULL;
    BSTNode* pre = NULL;
    s.push(root);
    while (!s.empty()){
        cur = s.top();
        if ((cur->left == NULL&&cur->right == NULL) || (pre != NULL && (pre==cur->left||pre==cur->right))){
            cout << cur->key << " ";
            s.pop();
            pre = cur;
        }
        else{
            if (cur->right != NULL){
                s.push(cur->right);
            }
            if (cur->left != NULL){
                s.push(cur->left);
            }
        }
    }
    cout << endl;
}
void preOrder(BSTNode* root){
    if (root != NULL){
        cout << root->key << endl;
        preOrder(root->left);
        preOrder(root->right);
    }
}
void inOrder(BSTNode* root){
    if (root != NULL){
        inOrder(root->left);
        cout << root->key << endl;
        inOrder(root->right);
    }
}
void postOrder(BSTNode* root){
    if (root != NULL){
        postOrder(root->left);
        postOrder(root->right);
        cout << root->key << endl;
    }
}
int main(){
    int a[] = { 10, 15, 200, 150, 30, 6, 1000 ,8,170};
    BSTNode *root=new BSTNode(10, NULL, NULL, NULL);
    for (int i = 1; i < 9; i++){
        BSTNode* node = new BSTNode(a[i]);
        BSTree_insert(root, node);

    }
    cout << "我们求取节点30的前驱:" << endl;
    BSTNode* node = BSTree_search(root, 30);
    BSTNode* pre_Node_30 = BSTree_predecess(node);
    if (pre_Node_30){
        cout <<"找到啦:"<< pre_Node_30->key << endl;
    }
    else{
        cout << "对不起,没有找到30的前驱节点!!!" << endl;
    }
    cout << "我们求取节点8的后继:" << endl;
    node = BSTree_search(root, 8);
    BSTNode* post_Node_8 = BSTree_suc(node);
    if (post_Node_8){
        cout << "找到啦:" << post_Node_8->key << endl;
    }
    else{
        cout << "对不起,没有找到8的后继节点!!!" << endl;
    }
    cout << "先序遍历: ";
    preorder_show(root);
    cout << "中序遍历: ";
    inorder_show(root);
    cout << "后序遍历: ";
    postorder_show(root);
    cout << "\n";
    cout << "先序遍历: "<<endl;
    preOrder(root);
    cout << "中序遍历: "<<endl;
    inOrder(root);
    cout << "后序遍历: "<<endl;
    postOrder(root);
    node = BSTree_search(root, 150);
    BSTree_remove_pre(node);
    cout << "删除节点150之后的先序遍历结果:" << endl;
    preorder_show(root);
    return 0;
}

运行结果:
这里写图片描述
这里写图片描述

参考博客:
二叉树删除规则: 二叉查找树的插入和删除详解
二叉树前驱和后继规则:二叉搜索树节点的前驱后继节点

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值