二叉搜索树---递归及非递归

二叉搜索树又称为二叉排序树,它为一棵空树,或者是一棵左子树所有节点的值比根节点小,右子树所有节点的值比根节点大的一棵树。

性质:
①.二叉搜索树中,最左边的结点值最小,最右边的结点值最大
②中序遍历一棵二叉搜索树,所有节点的值是按顺序排列的

   构造一棵二叉搜索树时,比较插入结点的key值,key小于根节点的_key时,向根节点的左边走,大于根节点的_key值时,向根节点的右边走;
   删除二叉搜索树中的某个结点时,分为四种情况;

删除二叉搜索树中某个节点的情况及处理方法如下:

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

二叉搜索树的基本操作代码如下:

BSTree.hpp

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

template<class k,class v>
struct BSNode
{
    BSNode(const k& key,const v& value)
        :_pLeft(NULL)
        ,_pRight(NULL)
        ,_key(key)
        ,_value(value)
    {}

    BSNode<k,v>* _pLeft;
    BSNode<k,v>* _pRight;

    k _key;
    v _value;
};

template<class k,class v>
class BSTree
{
    typedef BSNode<k,v> Node;
public:
    BSTree()
        :_pRoot(NULL)
    {}
    ~BSTree()
    {
        _DestroyBSTree(_pRoot);
    }
    BSTree<k,v>& operator=(const BSTree<k,v>& bst)
    {
        if(this!=&bst)
        {
            _DestroyBSTree(_pRoot);
            _pRoot=_CopyBSTree(bst._pRoot);
        }
        return *this;
    }

    Node* Find(const k& key)//查找某个节点--非递归
    {
        Node* pCur=_pRoot;
        while(pCur)
        {
            if(key==pCur->_key)
                return pCur;
            else if(key<pCur->_key)
                pCur=pCur->_pLeft;
            else
                pCur=pCur->_pRight;
        }
        return 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
            pParent->_pRight=pCur;
        return true;
    }
    void InOrder()//中序遍历
    {
        cout<<"InOrder:"<<endl;
        _InOrder(_pRoot);
        cout<<endl;
    }
    const k& GetMaxKey()const//找最右结点(最大)
    {
        assert(_pRoot);
        Node* pCur=_pRoot;
        while(pCur->_pRight)
            pCur=pCur->_pRight;
        return pCur->_key;
    }
    const k& GetMinKey()const//找最左结点(最小)
    {
        assert(_pRoot);
        Node* pCur=_pRoot;
        while(pCur->_pLeft)
            pCur=pCur->_pLeft;
        return pCur->_key;
    }

    bool Remove(const k& key)//删除key结点--非递归
    {
        //树为空,不能删除结点
        if(NULL==_pRoot)
            return false;
        //只有一个根节点,要删除的结点正好是根节点
        if(NULL==_pRoot->_pLeft && NULL==_pRoot->_pRight && key==_pRoot->_key)
        {                                                                     
            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;//找到了该节点
        }
        //已找到待删除结点---》1.没有左孩子,只有右孩子
                             //2.没有右孩子,只有左孩子
                            // 3.左右孩子都没有
                             //4.左右孩子都存在
                             //可以合并1,3 或2,3
        if(pCur)
        {   //1.没有左孩子,右孩子可能存在,也可能不存在(NULL)
            if(NULL==pCur->_pLeft)
            {
                if(pCur!=_pRoot)
                {
                    if(pCur==pParent->_pRight)
                        pParent->_pRight=pCur->_pRight;
                    else
                        pParent->_pLeft=pCur->_pRight;
                }
                else
                    _pRoot=pCur->_pRight;
            }
            //2.没有右孩子,左孩子可能存在,也可能不存在(NULL)
            else if(NULL==pCur->_pRight)
            {
                if(pCur!=_pRoot)
                {
                    if(pCur==pParent->_pRight)
                        pParent->_pRight=pCur->_pLeft;
                    else
                        pParent->_pLeft=pCur->_pLeft;
                }
                else
                    _pRoot=pCur->_pLeft;
            }
            //3.左右子树都存在
            else
            {
                //找中序遍历的第一个节点,为右子树中最小的结点
                //pParnet一直是firstInOrder的双亲
                pParent=pCur;//防止在找右子树中最小结点时,右子树没有左孩子,无法进入循环,pParent会一直为空
                Node* firstInOrder=pCur->_pRight;
                //找该节点的右子树中最左边的结点,即右子树中key最小的结点
                while(firstInOrder->_pLeft)
                {
                    pParent=firstInOrder;
                    firstInOrder=firstInOrder->_pLeft;
                }
                //交换key最小结点和根节点的值
                pCur->_key=firstInOrder->_key;
                pCur->_value=firstInOrder->_value;
                if(pParent->_pLeft==firstInOrder)
                    pParent->_pLeft=firstInOrder->_pRight;
                else
                    pParent->_pRight=firstInOrder->_pRight;
                pCur=firstInOrder;
            }
            delete pCur;
            pCur=NULL;
            return true;
        }
        return false;
    }
//递归版本
    //Node* Find(const k& key)//递归找结点
    //{
    //  Node* pCur=NULL;
    //  pCur=_Find(_pRoot,key);
    //  cout<<pCur->_key<<endl;
 //       return pCur;
    //}

 //   bool Insert(const k& key,const v& value)//递归插入
    //{
 //       return _Insert(_pRoot,key,value);
    //}

    //bool Remove(const k& key)//递归删除
    //{
 //       return _Remove(_pRoot,key);
    //}

protected:
    Node* _CopyBSTree(Node* pRoot)//拷贝
    {
        Node* pNewRoot=NULL;
        if(pRoot)
        {
            //拷贝根节点
            pNewRoot=new Node(pRoot->_value);
            //拷贝左子树
            pNewRoot->_pLeft=_CopyBSTree(pRoot->_pLeft);
            //拷贝右子树
            pNewRoot->_pRight=_CopyBSTree(pRoot->_pRight);
        }
        return pNewRoot;
    }

    void _DestroyBSTree(Node* &pRoot)
    {
        if(pRoot)
        {
            _DestroyBSTree(pRoot->_pLeft);
            _DestroyBSTree(pRoot->_pRight);
            delete pRoot;
            pRoot=NULL;
        }
    }

    void _InOrder(Node* pRoot)
    {
        if(pRoot)
        {
            _InOrder(pRoot->_pLeft);
            cout<<pRoot->_key<<" ";
            _InOrder(pRoot->_pRight);
        }
    }

 //   Node* _Find(Node* pRoot,const k& key)//递归找
    //{
    //  if(NULL==pRoot)
    //      return NULL;
    //  if(key==pRoot->_key)
    //      return pRoot;
    //  else if(key<pRoot->_key)
    //      return _Find(pRoot->_pLeft,key);
    //  else
    //      return _Find(pRoot->_pRight,key);
    //}
    //bool _Insert(Node*& pRoot,const k& key,const v& value)//递归插入
    //{
    //  if(NULL==pRoot)
    //  {
    //      pRoot=new Node(key,value);
    //      return true;
    //  }
    //  if(key<pRoot->_key)
    //      return _Insert(pRoot->_pLeft,key,value);
    //  else if(key>pRoot->_key)
    //      return _Insert(pRoot->_pRight,key,value);
    //  else 
    //      return false;
    //}

    //bool _Remove(Node*& pRoot,const k& key)//递归删除
    //{
    //  if(NULL==pRoot)
    //      return false;
    //  else
    //  {
    //      if(key<pRoot->_key)
    //          _Remove(pRoot->_pLeft,key);
    //      else if(key>pRoot->_key)
    //          _Remove(pRoot->_pRight,key);
    //      else
    //      {
    //          Node* pDel=pRoot;
    //          if(NULL==pRoot->_pLeft)
    //          {
    //              pRoot=pRoot->_pRight;
    //              delete pDel;
    //              return true;
    //          }
    //          else if(NULL==pRoot->_pRight)
    //          {
    //              pRoot=pRoot->_pLeft;
    //              delete pDel;
    //              return true;
    //          }
    //          else
    //          {
    //              Node* firstInOrder=pRoot->_pRight;
    //              while(firstInOrder->_pLeft)//找要删除结点的右子树中最小结点进行交换
    //                  firstInOrder=firstInOrder->_pLeft;
    //              pDel->_key=firstInOrder->_key;
    //          
    //              return _Remove(pRoot->_pRight,firstInOrder->_key);
    //          }
    //      }
    //  }
    //  return false;
    //}
private:
    Node* _pRoot;
};

测试代码:
BST.cpp

#include"BSTree.hpp"

void Test1()
{
    BSTree<int,int> bst;
    int a[]={5,3,4,1,7,8,2,6,0,9};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.InOrder();
    bst.Find(8);
    cout<<bst.GetMinKey()<<endl;
    cout<<bst.GetMaxKey()<<endl;
}

void Test2()//情况三①②及情况一
{
    BSTree<int,int> bst;
    int a[]={5,3,4,1,7,8,2,6,0,9};
    //int a[]={5,3,4,1,8,2,6,7,0,9};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.Remove(8);
    bst.InOrder();
    bst.Remove(6);
    bst.InOrder();

}
void Test3()//情况三中的③
{
    BSTree<int,int> bst;
    int a[]={5,7,8,6,9};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.Remove(5);
    bst.InOrder();
}

void Test4()//情况二
{
    BSTree<int,int> bst;
    int a[]={5,3,4,1,7,6,0};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.Remove(1);
    bst.InOrder();
    bst.Remove(7);
    bst.InOrder();

}


void Test5()//情况四
{
    BSTree<int,int> bst;
    int a[]={5,3,4,1,7,8,2,6,0,9};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.Remove(5);
    bst.InOrder();
    bst.Remove(7);
    bst.InOrder();

}
void Test6()//情况四
{
    BSTree<int,int> bst;
    int a[]={5,3,4,1,7,8,2,0,9};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.Remove(5);
    bst.InOrder();
}
int main()
{
    Test1();
    //Test2();
    //Test3();
    //Test4();
    //Test5();
    //Test6();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值