大话数据结构之二叉搜索树

二叉搜索树

参考大话数据结构和B站up主码农论坛

与之前博客大话数据结构之二叉树c++实现相关联

file BSTree.h

#pragma once
#include "BinaryTree.h"

class BSTree
{
public:
    BSTree(void);
    BSTree(ElemType *element, int len);
    ~BSTree(void);

    void CreateBSTree(BiTree *pTT, ElemType *pe, int len);
    bool InsertRecur(BiTree *pTT, ElemType *element);
    BiTNode *FindRecur(BiTree TT, ElemType *element);
    BiTNode *Find(BiTree TT, ElemType *element);
    
    bool Delete(BiTree *pTT, ElemType *pelement);

    BiTree GetBiTree()
    {
        return m_BSTree;
    }

    BiTree *GetPointerOfBiTree()
    {
        return &m_BSTree;
    }

    void BSTLevelOrder();
private:    
    BiTree m_BSTree;
};


file BSTree.cpp

#include "BSTree.h"
#include <string.h>

BSTree::BSTree()
{
}

BSTree::BSTree(ElemType *element, int len)
            : m_BSTree(nullptr)
{
    CreateBSTree(&m_BSTree, element, len);
}

BSTree::~BSTree(void)
{
}

void BSTree::CreateBSTree(BiTree *pTT, ElemType *pe, int len)
{
    for (int i=0; i<len; ++i)
    {
        InsertRecur(pTT, &pe[i]);
    }
}

bool BSTree::InsertRecur(BiTree *pTT, ElemType *element)
{
    // 如果当前子树为空,创建子树的根结点。
    if (*pTT == nullptr)
    {
        *pTT = new BiTNode;
        memcpy(&(*pTT)->data, element, sizeof(ElemType));
        (*pTT)->lchild = (*pTT)->rchild = nullptr;
        return true;
    }

    if ((*pTT)->data == *element) return false;

    if (*element < (*pTT)->data) 
        InsertRecur(&(*pTT)->lchild, element);
    else 
        InsertRecur(&(*pTT)->rchild, element);
}

BiTNode *BSTree::FindRecur(BiTree TT, ElemType *element)
{
    if (TT == nullptr) return nullptr;

    if (*element == TT->data) return TT;

    if (*element < TT->data) 
        return FindRecur(TT->lchild, element);
    else if (*element > TT->data) 
        return FindRecur(TT->rchild, element);
}

BiTNode *BSTree::Find(BiTree TT, ElemType *element)
{
    BiTNode *pNode = TT;
    while (pNode)
    {
        if (pNode->data == *element) return pNode;

        if (pNode->data < *element)
            pNode = pNode->rchild;
        else if (pNode->data > *element)
            pNode = pNode->lchild;
    }
    return nullptr;
}

bool BSTree::Delete(BiTree *pTT, ElemType *pelement)
{
    if (*pTT == nullptr) return false;

    // 1)如果树只有根结点,并且待删除的结点就是根结点。
    if ( ((*pTT)->data == *pelement) && ((*pTT)->lchild == nullptr) && ((*pTT)->rchild == nullptr) )
    {
        delete (*pTT); (*pTT) = nullptr; return true;
    }

    // 查找待删除的结点。
    BiTNode *pParents = nullptr;
    BiTNode *pCurrent = (*pTT);
    int iLeftOrRight = 0; // 记录pCurrent是双亲结点的左子树还是右子树,0-左子树;1-右子树

    while ( pCurrent )
    {
        if ( pCurrent->data == *pelement ) break; // 成功找到。

        pParents = pCurrent;
        if ( *pelement < pCurrent->data ) 
        {
            pCurrent = pCurrent->lchild;
            iLeftOrRight = 0;
        }
        else 
        {
            pCurrent = pCurrent->rchild;
            iLeftOrRight = 1;
        }
    }

    if ( pCurrent == nullptr ) return false;

    // 2)如果待删除的结点ss是叶结点,直接删除,不会破坏二叉排序树的性质。
    if ( (pCurrent->lchild == nullptr) && (pCurrent->rchild == nullptr) )
    {
        delete pCurrent;

        if ( iLeftOrRight == 0 )
            pParents->lchild = nullptr;
        else 
            pParents->rchild = nullptr;
            
        return true;
    }

    // 3)如果待删除的结点ss只有左子树或右子树,则让子树代替自己。
    if ( (pCurrent->lchild == nullptr) || (pCurrent->rchild == nullptr) )
    {
        if ( pCurrent->lchild != nullptr ) // 有左子树。
        {
            // 修改双亲结点pParents的左或右指针指向pCurrent的左子树。
            if ( iLeftOrRight == 0 )
                pParents->lchild = pCurrent->lchild;
            else
                pParents->rchild = pCurrent->lchild;
            delete pCurrent;
        }
        else // 有右子树。
        {
            // 修改双亲结点pParents的左或右指针指向pCurrent的右子树。
            if ( iLeftOrRight == 0 )
                pParents->lchild = pCurrent->rchild;
            else
                pParents->rchild = pCurrent->rchild;
            delete pCurrent;
        }

        return true;
    }

    // 4)如果待删除的结点ss有左子树和右子树,让左子树最右侧的结点代替自己,然后再删除左子树最右侧的结点。
    // 也可以让右子树最左侧的结点代替自己,然后删除右子树最左侧的结点。
    BiTNode *pParents1 = pCurrent; // 记录双亲结点的地址
    
    BiTNode *pCurrent1 = pCurrent->rchild; // 用于查找的临时指针
    //BiTNode *pCurrent1 = pCurrent->lchild; // 用于查找的临时指针

    int iLeftOrRight1 = 0; // 记录ss1是双亲结点的左子树还是右子树,0-左子树;1-右子树

    // 右子树向左走到尽头。|| 左子树向右走到尽头。   
    while ( pCurrent1->lchild )
    //while ( pCurrent1->rchild )
    {
        iLeftOrRight1 = 0;
        //iLeftOrRight1 = 1;
        pParents1 = pCurrent1;
        pCurrent1 = pCurrent1->lchild;
        //pCurrent1 = pCurrent1->rchild;
    }

    // 把右子树最左侧的结点值复制到结点pCurrent中 || 把左子树最右侧的结点值复制到结点pCurrent中。
    memcpy(&pCurrent->data,&pCurrent1->data,sizeof(ElemType));

    // 右子树最左侧的结点pCurrent1必定无左子树 || 左子树最右侧的结点pCurrent1必定无右子树。
    // 修改双亲结点pss1的左或右指针指向ss1的左子树,ss1的左子树可以为空。
    if ( iLeftOrRight1 == 0 )
        pParents1->lchild = pCurrent1->rchild;
    else 
        pParents1->rchild = pCurrent1->rchild;
    /*if ( iLeftOrRight1 == 0 )
        pParents1->lchild = pCurrent1->lchild;
    else 
        pParents1->rchild = pCurrent1->lchild;*/

    delete pCurrent1;
    return true;
}

void BSTree::BSTLevelOrder()
{
    queue<BiTree> qq; 
    qq.push(m_BSTree);

    while (!qq.empty())
    {
        cout << qq.front()->data << " ";
        BiTNode *tmp = qq.front();
        qq.pop();

        if (tmp->lchild != nullptr) qq.push(tmp->lchild);
        if (tmp->rchild != nullptr) qq.push(tmp->rchild);
    }
    return;
}

file main.cpp

#include <queue>
#include <stack>
#include "BinaryTree.h"
#include "BSTree.h"

void myPrint(char *strInfo)
{
    cout << "\n" << strInfo << "..." << endl;
}

int main()
{  
    BinaryTree myBiTree;
    myPrint("层序遍历"); myBiTree.LevelOrder();
    myPrint("先序遍历"); myBiTree.PreOrder();
    myPrint("先序遍历递归版"); myBiTree.PreOrderRecur();
    myPrint("中序遍历"); myBiTree.InOrder();
    myPrint("中序遍历递归版"); myBiTree.InOrderRecur();
    myPrint("后序遍历"); myBiTree.PostOrder();
    myPrint("后序遍历递归版"); myBiTree.PostOrderRecur();

    cout << endl;
    ElemType arr[]={50,66,60,26,21,30,70,68}; 
    BSTree myBSTree(arr, sizeof(arr)/sizeof(ElemType));
    myPrint("层序遍历"); myBSTree.BSTLevelOrder();
    BiTNode *tmpRecur = myBSTree.FindRecur(myBSTree.GetBiTree(), &arr[4]);
    myPrint("找到节点tmpRecur");
    std::cout << tmpRecur->data << std::endl;

    BiTNode *tmp = myBSTree.Find(myBSTree.GetBiTree(), &arr[4]);
    myPrint("找到节点tmp");
    std::cout << tmp->data << std::endl;

    /*myPrint("删除只有左子树的结点");
    if ( myBSTree.Delete(myBSTree.GetPointerOfBiTree(), &arr[6]))
    {
    myPrint("层序遍历"); myBSTree.BSTLevelOrder();
    }

    myPrint("删除叶结点");
    if ( myBSTree.Delete(myBSTree.GetPointerOfBiTree(), &arr[2]))
    {
    myPrint("层序遍历"); myBSTree.BSTLevelOrder();
    }*/

    myPrint("删除既有左子树又有右子树的结点");
    if ( myBSTree.Delete(myBSTree.GetPointerOfBiTree(), &arr[0]))
    {
        myPrint("层序遍历"); myBSTree.BSTLevelOrder();
    }

    system("pause");
    return 0;
}

/*
    // 手工构造一个如下结构的二叉树。
             1
          /     \
         2       3
        / \     /
       4   5   6
      / \ / \
     7  8 9  0
*/

/*
  // 用数组arr中的序列构建二叉排序树TT。
  // 构建的二叉排序树将如下:
              50
           /     \
          26      66
         /  \    /  \
        21  30 60   70
                   /
                  68
  */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值