二叉搜索树

二叉搜索树
当它不为空时,满足如下性质:
当它的左子树不为空时,左子树所有节点都小于根结点的值
当它的右子树不为空时,右子树所有节点都大于根结点的值
它的左右子树分别为二叉搜索树

搜索节点

  • 如果根结点不为空
    • 如果key和节点的值相等,返回
    • 如果key小于节点的值,去左子树查找
    • 如果key大于节点的值,去右子树查找

插入节点

  • 如果根结点为空
    • 直接插入
  • 搜索要插入的位置:
    • 当前节点不为空时
      • 待插入key小于节点值,向左子树走
      • 待插入key大于节点值,向右子树走
      • 如果相等,直接返回
  • 插入节点:
    • 如果key小于当前节点父节点的值
      • 插入到左子树
    • 如果key大于当前节点父节点的值
      • 插入到右子树

删除节点

这里写图片描述

代码:

#include<iostream>
using namespace std;

template<typename T>
struct  BinarySearchNode
{
    BinarySearchNode* _pLeft;
    BinarySearchNode* _pRight;
    T _data;
    BinarySearchNode(const T& data=T())
        :_pLeft(NULL)
        , _pRight(NULL)
        , _data(data)
    {}
};

template<typename T>
class  BinarySerachTree
{
    typedef BinarySearchNode<T> Node;
    typedef Node* pNode;
public:
    BinarySerachTree()
        :_pRoot(NULL)
    {}

    bool Insert(const T& data)
    {
        if (NULL == _pRoot)
        {
            _pRoot = new Node(data);
            return true;
        }
        pNode pCur = _pRoot;
        pNode pParent = pCur;

        while (pCur)
        {
            if (pCur->_data > data)
            {
                pParent = pCur;
                pCur = pCur->_pLeft;
            }
            else if (pCur->_data < data)
            {
                pParent = pCur;
                pCur = pCur->_pRight;
            }
            else
                return false;
        }
        if (pParent->_data < data)
            pParent->_pRight = new Node(data);
        else
            pParent->_pLeft = new Node(data);

        return true;
    }

    pNode Find(const T& data)
    {
        if (NULL == _pRoot)
            return NULL;

        pNode pCur = _pRoot;
        while (pCur)
        {
            if (data == pCur->_data)
                return pCur;
            else if (pCur->_data < data)
                pCur = pCur->_pRight;
            else
                pCUr = pCur->_pLeft;
        }
        return pCur;
    }

    bool Delete(const T& data)
    {
        if (NULL == _pRoot)
            return false;

        if (NULL == _pRoot->_pLeft && NULL == _pRoot->_pRight)//只有一个节点的情况
        {
            if (data == _pRoot->_data)
            {
                delete _pRoot;
                _pRoot = NULL;
                return true;
            }
            else
                return false;
        }

        pNode pCur = _pRoot;
        pNode pDel = NULL;
        pNode pParent = pCur;


        while (pCur)
        {
            if (data == pCur->_data)
            {
                break;
            }
            else if (pCur->_data < data)
            {
                pParent = pCur;
                pCur = pCur->_pRight;
            }
            else
            {
                pParent = pCur;
                pCur = pCur->_pLeft;
            }
        }
        if (NULL == pCur)
            return false;

        if (NULL == pCur->_pLeft)//要删除节点左边为空或者左右子树都为空
        {
            if (pCur != _pRoot)
            {
                if (pParent->_pLeft == pCur)//要删除节点位于上一节点的左边
                {
                    pParent->_pLeft = pCur->_pRight;
                }
                else if (pParent->_pRight == pCur)
                {
                    pParent->_pRight = pCur->_pRight;
                }
            }
            else
                _pRoot = pCur->_pRight;

        }
        else if (NULL == pCur->_pRight)//待删节点的右边为空
        {
            if (pCur != _pRoot)
            {
                if (pParent->_pLeft == pCur)
                {
                    pParent->_pLeft = pCur->_pLeft;
                }
                else if (pParent->_pRight == pCur)
                {
                    pParent->_pRight = pCur->_pLeft;
                }
            }
            else
                _pRoot = pCur->_pLeft;
        }
        else
            //待删节点的左右子树都不为空,
            //找到左子树的最右边节点替换待删节点,或者找到右子树的最左边替换待删节点
            //然后删除找到的节点
        {
            pNode pDel = pCur->_pRight;//右子树的根结点
            pParent = pCur;
            while (pDel->_pLeft)
            {
                pParent = pDel;
                pDel = pDel->_pLeft;
            }
            pCur->_data = pDel->_data;
            pCur = pDel;

            if (pDel == pParent->_pLeft)
                pParent->_pLeft = pDel->_pRight;
            else if (pDel == pParent->_pRight)
                pParent->_pRight = pDel->_pRight;
        }
        delete pCur;
        pCur = NULL;
        return true;
    }
    void InOder()
    {
        if (_pRoot == NULL)
            return;
        cout << "中序遍历:";
        _InOder(_pRoot);
        cout << endl;
    }
private:
    void _InOder(pNode pRoot)
    {
        if (pRoot == NULL)
            return;
        _InOder(pRoot->_pLeft);
        cout << pRoot->_data << " ";
        _InOder(pRoot->_pRight);
    }
private:
    pNode _pRoot;
};

void BinarySearchTreeTest()
{
    BinarySerachTree<int> bs;
    int arr[] = {5,7,8,9,6,3,4,1,0,2};
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    {
        bs.Insert(arr[i]);
    }
    bs.InOder();
    //bs.Delete(5);
    bs.Delete(7);
    bs.InOder();
}

递归实现代码:

#pragma once

#include<iostream>
using namespace std;

template<typename T>
struct BinSearchNode
{
    BinSearchNode<T>* _pLeft;
    BinSearchNode<T>* _pRight;
    T _data;
    BinSearchNode(const T& data = T())
        :_pLeft(NULL)
        , _pRight(NULL)
        , _data(data)
    {}
};

template<typename T>
class BinSearchTree
{
    typedef BinSearchNode<T> Node;
    typedef Node* pNode;
public:
    BinSearchTree()
        :_pRoot(NULL)
    {}

    bool Insert(const T& data)
    {
        return _Insert(_pRoot, data);
    }

    pNode Find(const T& data)
    {
        return _Find(_pRoot, data);
    }

    bool Delete(const T& data)
    {
        return _Delete(_pRoot, data);
    }

    void Inder()
    {
        if (NULL == _pRoot)
            return;
        cout << "中序遍历:";
        _Inder(_pRoot);
        cout << endl;
    }
private:

    void _Inder(pNode pRoot)
    {
        if (NULL == pRoot)
            return;
        _Inder(pRoot->_pLeft);
        cout << pRoot->_data << " ";
        _Inder(pRoot->_pRight);
    }

    bool _Delete(pNode& pRoot, const T& data)
    {
        if (NULL == pRoot)
            return false;
        if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)//只有一个节点
        {
            if (data == pRoot->_data)
            {
                delete pRoot;
                pRoot = NULL;
                return true;
            }
            else
                return false;
        }
        if (data < pRoot->_data)
            return _Delete(pRoot->_pLeft, data);
        else if (data > pRoot->_data)
            return _Delete(pRoot->_pRight,data);
        else
        {
            pNode pDel = pRoot;
            if (NULL == pRoot->_pLeft)//当前子树的左子树为空,让根结点指向根结点的左子树
            {
                pRoot = pRoot->_pRight;
                delete pDel;
                pDel = NULL;
                return true;
            }
            else if (NULL == pRoot->_pRight)
            {
                pRoot = pRoot->_pLeft;
                delete pDel;
                pDel = NULL;
                return true;
            }
            else//左右子树都不为空
            {
                //找到左右子树的最左边节点-背锅侠,替换根结点
                pNode pDel = pRoot;
                pDel = pRoot->_pRight;
                while (pDel->_pLeft)
                    pDel = pDel->_pLeft;

                pRoot->_data = pDel->_data;
                //删除背锅侠
                return _Delete(pRoot->_pRight,pDel->_data);
            }

        }
    }

    pNode _Find(pNode pRoot, const T& data)
    {
        if (NULL == pRoot)
            return NULL;

        if (data == pRoot->_data)
            return pRoot;
        else if (data < pRoot->_data)
            return _Find(pRoot->_pLeft, data);
        else
            return _Find(pRoot->_pRight,data);
    }

    bool _Insert(pNode& pRoot, const T& data)
    {
        if (NULL == pRoot)
        {
            pRoot = new Node(data);
            return true;
        }
        if (data == pRoot->_data)
            return false;
        else if (data < pRoot->_data)
            return _Insert(pRoot->_pLeft, data);
        else
            return _Insert(pRoot->_pRight,data);
    }

private:
    pNode _pRoot;
};


void BinarySearchTreeTest()
{
    BinSearchTree<int> bs;
    //int arr[] = { 5, 7, 8, 9, 6, 3, 4, 1, 0, 2 };
    int arr[] = {5,7,6,9};
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    {
        bs.Insert(arr[i]);
    }
    bs.Inder();
    //bs.Delete(5);
    bs.Delete(9);
    bs.Inder();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值