动态查找之-二叉排序树

二叉排序树简叙


这里写图片描述

从图上可得出二叉排序树的基本概念。

  1. 左子树小于根,右子树大于根
  2. 中序遍历后有序
  3. 树中最小的树在最左边,最大的在最右边

这里主要分析一下二叉排序树的插入和删除。

插入

        pCur = new Node(key, value);
        if (key < pParent->_key)
        {
            pParent->_pLeft = pCur;
        }

        else if(key>pParent->_key)
        {
            pParent->_pRight = pCur;
        }       

这里只截取插入时的代码,即因为已经找到插入位置。
我们只需创建一个新的节点,然后判断待插入的key值和当前根节点的大小,即可进行插入,二叉排序树的插入都是在空指针域出进行。


删除

整个程序应该就删除比较复杂一点,只要能将它的示意图画出来,其实就很简单了。
删除的几种情况:
这里写图片描述
画图的水平略显粗糙

如果左右子树都没有的话,直接进行删除就好了,如果是只有右子树或者左子树,那就要分情况了,如下:

这里写图片描述
单独没有右子树和单独没有左子树同理。

如果左右都有的话:
这里写图片描述


下面是整个代码

#pragma once
#include<iostream>
#include<stdlib.h>
using namespace std;


template <class K,class V>
struct BSTNode
{
    BSTNode(const K& key,const V& value)
    : _pLeft(NULL)
    , _pRight(NULL)
    , _key(key)
    , _value(value)
    {}

    BSTNode<K,V>* _pLeft;
    BSTNode<K,V>* _pRight;
    K _key;
    V _value;
};

template <class K,class V>
class BSTree
{
    typedef BSTNode<K, V> Node;
public:

    BSTree()
        :_pRoot(NULL)
    {}


    bool Insert(const K& key, const V& value)
    {
        if (NULL == _pRoot)
        {
            _pRoot = new Node(key, value);
            return true;
        }
        Node* pCur = _pRoot;
        Node* pParent = NULL;

        while (pCur)
        {
            if (key < pCur->_key)
            {
                pParent = pCur;//更新双亲
                pCur = pCur->_pLeft;
            }
            else if (key>pCur->_key)
            {
                pParent = pCur;
                pCur = pCur->_pRight;
            }
            else
            {
                return false;
            }
        }

        //找到了插入的位置,然后创建待插入的结点
        pCur = new Node(key, value);
        if (key < pParent->_key)
        {
            pParent->_pLeft = pCur;
        }

        else if (key>pParent->_key)
        {
            pParent->_pRight = pCur;
        }
        return true;
    }

    bool Remove(const K& key)
    {
        if (NULL == _pRoot)
            return false;

        if (NULL == _pRoot->_pLeft&& NULL == _pRoot->_pRight)
        {
            delete _pRoot;
            _pRoot= NULL;
            return true;
        }
        //开始找删除的位置
        Node *pCur = _pRoot;
        Node *pParent = NULL;
        while (pCur)
        {
            if (key < pCur->_key)
            {
                pParent = pCur;
                pCur = pCur->_pLeft;
            }
            else if (key>pCur->_key)
            {
                pParent = pCur;
                pCur = pCur->_pRight;
            }
            else
                break;
        }
        //出了循环,位置肯定找到了
        if (pCur == NULL)
        {
            return false;
        }

        if (NULL == pCur->_pLeft)
        {
            if (pCur->_key == key)//判断是否为根节点
            {
                _pRoot = pCur->_pRight;
                delete pCur;
                pCur = NULL;
                return true;
            }
            else if (pParent->_pLeft == pCur)//判断是否为双亲的左结点
            {
                pParent->_pLeft = pCur->_pRight;
            }
            else//双亲的右结点
            {
                pParent->_pRight = pCur->_pRight;
            }
        }

        else if (NULL == pCur->_pRight)
        {
            if (pCur->_key == key)
            {
                _pRoot = pCur->_pLeft;
                delete pCur;
                pCur = NULL;
                return true;
            }
            else if (pParent->_pRight = pCur)
            {
                pParent->_pRight = pCur->_pLeft;
            }
            else
            {
                pParent->_pLeft = pCur->_pLeft;
            }
        }
        else//到了这里,说明待删除的结点左右孩子都有
        {
            Node* sub = pCur;
            Node* First = pCur->_pRight;
            if (First->_pLeft)
            {
                sub = First;
                First = First->_pLeft;
            }
            swap(pCur->_key, First->_key);
            swap(pCur->_value, First->_value);
            pCur = First;
            if (pCur->_pLeft == NULL)
            {
                if (sub->_pLeft == pCur)
                {
                    sub->_pLeft = pCur->_pRight;
                }
                else
                {
                    sub->_pRight = pCur->_pRight;
                }
            }
            else if (pCur->_pRight == NULL)
            {
                if (sub->_pLeft == pCur)
                {
                    sub->_pLeft = pCur->_pLeft;
                }
                else
                {
                    sub->_pLeft = pCur->_pLeft;
                }
            }
        }
        delete pCur;
        pCur = NULL;
        return true;
    }



    Node* Find(const K& key)
    {
        if (NULL == _pRoot)
            return NULL;

        Node *pCur = _pRoot;
        while (pCur)
        {
            if (key < pCur->_key)
                pCur = pCur->_pLeft;
            else if (key>pCur->_key)
                pCur = pCur->_pRight;
            else
                break;
        }
        return pCur;
    }

    bool Insert_R(const K& key, const V& value)
    {
        return _Insert_R(_pRoot, key, value);
    }

    bool Remove_R(const K& key)
    {
        return _Remove_R(_pRoot, key);
    }

    void MidOrder()
    {
        _MidOrder(_pRoot);
        cout << endl;
    }



protected:
    bool _Insert_R(Node*& pRoot, const K& key, const V& value)
    {
        if (NULL == pRoot)
        {
            pRoot = new Node(key, value);
            return true;
        }
        if (key < pRoot->_key)
            return _Insert_R(pRoot->_pLeft, key, value);
        else if (key>pRoot->_key)
            return _Insert_R(pRoot->_pRight, key, value);
        else
            return false;
    }

    bool _Remove_R(Node *&pRoot, const K&key)
    {
        if (NULL == pRoot)
            return false;
        if (key > pRoot->_pLeft)
            return _Remove_R(pRoot->_pRight, key);
        else if (key < pRoot->_key)
            return _Remove_R(pRoot->_pLeft, key);
        else
        {
            Node *pCur = pRoot;
            if (pRoot->_pLeft == NULL)
                pRoot = pRoot->_pRight;
            else if (pRoot->_pRight == NULL)
                pRoot = pRoot->_pLeft;
            else
            {
                Node *First = pRoot->_pRight;
                while (First->_pLeft)
                {
                    First = First->_pLeft;
                }
                swap(pCur->_key, First->_key);
                swap(pCur->_value, First->_value);
                return _Remove_R(pRoot->_pRight, key);
            }
            delete pCur;
            pCur = NULL;
            return true;
        }
    }


    void _MidOrder(Node* _pRoot)
    {
        if (NULL == _pRoot)
            return;
        _MidOrder(_pRoot->_pLeft);
        cout << _pRoot->_key << " ";
        _MidOrder(_pRoot->_pRight);
    }



protected:
    BSTNode<K, V>* _pRoot;

};

最后是测试代码:

#include"5_15SortBinaryTree.h"

int main()
{
    int a[10] = { 5, 3, 1, 4, 0, 2, 7, 6, 8, 9 };
    BSTree<int, int> s;
    for (int idx = 0; idx < 10; idx++)
    {
        s.Insert_R(a[idx], idx);
    }
    s.MidOrder();
    s.Remove(5);
    s.MidOrder();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值