二叉搜索树

先建立一个节点的类

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值