C++实现二叉查找树,有兴趣的可以互相交流

最近在研究数据结构这本书,自己动手实现的一个二叉查找排序树的类BinSortTree,实现数据的插入,查找,删除,层序遍历,中序遍历等操作,熟悉数据结构的朋友都知道,根据二叉排序树的定义,中序遍历后得到的序列就是按照从小到大的顺序排列的,而最后删除二叉排序树的时候,要先删除子节点,才能删除父节点,其实就是一个后续遍历的过程。现在把代码分享一下,供大家参考学习。其实这个跟stl的set容器已经十分相似,只是set使用查找性能更优越的红黑树来实现

BinSortTree.h

//二叉排序树的类,实现插入数据,查找数据,插入数据、删除数据
#include <iostream>

//定义节点结构体
class Node
{
    public:
        int nData;//数据
        Node *pLeftChild;//左子树
        Node *pRightChild;//右子树
        Node(int nData):pLeftChild(NULL),pRightChild(NULL),nData(nData)
    {
    }
};

//定义排序树的类
class BinSortTree
{
    public:
        BinSortTree();
        ~BinSortTree();//在析构函数中释放所有分配的节点
        bool Insert(int nData);//插入一个节点
        bool Erase(int nErase);//根据关键字删除节点
        int  GetSize() { return m_nSize;}
        //根据关键字查找指定的节点,如果找到了,则返回该节点的指针
        //如果没有找到,返回NULL
        Node* Find(int nFind);
        void Traversal(int nType = 0);//遍历二叉树,,0为中序遍历,1为层序遍历

    private:
        Node *m_pRoot;//根节点
        int   m_nSize;//节点的个数

    private:
        void DeleteNode(Node *pNode);
        void InorderTraversal(Node *pNode);//中序遍历二叉树
        void LevelOrderTraversal(Node *pNode);//层序遍历
        bool Erase(Node **pRoot,int nData);
};

BinSortTree.cpp

#include <iostream>
#include <set>
#include <queue>
#include "BinSortTree.h"
using namespace std;

BinSortTree::BinSortTree()
{
    m_pRoot = NULL;
    m_nSize = 0;
}

BinSortTree::~BinSortTree()
{
    //析构每一个节点
    if (NULL != m_pRoot)
    {
        DeleteNode(m_pRoot); 
    }
}

void BinSortTree::DeleteNode(Node *pNode)
{
    //检查该节点是否存在左子树或者右子树,如果有,递归调用删除
    if (NULL != pNode->pLeftChild)
    {
        DeleteNode(pNode->pLeftChild);
    }
    if (NULL != pNode->pRightChild)
    {
        DeleteNode(pNode->pRightChild);
    }
    cout << "删除节点:" << pNode->nData << endl;
    delete pNode;
}


Node* BinSortTree::Find(int nFind)
{
    Node *pTemp = m_pRoot;
    //类似于二分查找
    while(pTemp != NULL)
    {
        if (nFind == pTemp->nData)
        {
            //说明已经找到,返回这个指针
            return pTemp;
        }
        else if (nFind < pTemp->nData)
        {
            //从左子树中查找
            pTemp = pTemp->pLeftChild;
        }
        else
        {
            pTemp = pTemp->pRightChild;
        }
    }

    return NULL;
}

bool BinSortTree::Insert(int nData) 
{
    Node *pPre = m_pRoot;
    Node *pNext = m_pRoot;
    //先在树中查找,如果找到了就返回,如果没有找到,则在最后一个节点插入
    while(pNext != NULL)
    {

        pPre = pNext;
        if (nData == pNext->nData)
        {
            return false;
        }
        else if (nData < pNext->nData)
        {
            pNext = pNext->pLeftChild;
        }
        else
        {
            pNext = pNext->pRightChild;
        }

    }
    //说明没有找到,则插入一个新节点
    Node* pNew = new Node(nData);
    //如果是一棵空树,则直接插入
    if (m_pRoot == NULL)
    {
        m_pRoot = pNew;
        ++m_nSize;//节点数加1
        return true;
    }
    //如果不是一棵空树,判断是插入到最后一个节点的左子树还是右子树
    if (nData < pPre->nData)
    {
        pPre->pLeftChild = pNew;
    }
    else
    {
        pPre->pRightChild = pNew;
    }

    ++m_nSize;
    return true;
}

bool BinSortTree::Erase(int nData)
{
    return Erase(&m_pRoot, nData);
}

bool BinSortTree::Erase(Node **pRoot, int nData)
{
    Node **pPre = pRoot;//保存指向删除节点指针的指针,便于以后修改
    Node *pFind = *pRoot;
    //先在树中查找
    while(pFind != NULL)
    {
        if (nData == pFind->nData)
        {
            break;
        }
        else if (nData < pFind->nData)
        {
            pPre = &pFind->pLeftChild;
            pFind = pFind->pLeftChild;
        }
        else
        {
            pPre = &pFind->pRightChild;
            pFind = pFind->pRightChild;
        }

    }
    if (NULL == pFind)
    {
        return false;    
    }
    /******分四种情况******/
    //1、如果要删除的节点没有子节点
    if (pFind->pLeftChild == NULL && pFind->pRightChild == NULL)
    {
        //直接删除该节点
        delete pFind;
       --m_nSize;//节点数减1
        //将指向该节点的指针置空
       *pPre = NULL;
        return true;
    }

    //2、如果要删除的节点只有左孩子节点
    if (NULL != pFind->pLeftChild && NULL == pFind->pRightChild)
    {
        //被删除节点的双亲节点重新指向被删除节点的左孩子节点
        *pPre = pFind->pLeftChild;
        //删除节点
        delete pFind;
        --m_nSize;//节点数减1
        return true;
    }

    //3、如果要删除的节点只有右孩子节点
    if (NULL == pFind->pLeftChild && NULL != pFind->pRightChild)
    {
        //被删除节点的双亲节点重新指向被删除节点的右孩子节点
        *pPre = pFind->pRightChild;
        //删除节点
        delete pFind;
        --m_nSize;//节点数减1
        return true;
    }

    //4、如果要删除的节点有左右孩子节点
    if (NULL != pFind->pLeftChild && NULL != pFind->pRightChild)
    {
        //找出关键字值大于被删除节点的关键字值中的最小值,即寻找被删除节点右子树中的最左值
        Node *pTarget = pFind->pRightChild;//最左值的指针
        Node *pNext = pFind->pRightChild;
        while(NULL != pNext)
        {
            pTarget = pNext;
            pNext = pTarget->pLeftChild;
        }
        //交换最左节点和被删除节点的值
        pFind->nData = pTarget->nData;
        //以被删除节点的右节点为根节点,最左节点关键字的值为删除目标,再次调用删除函数
        return Erase(&pFind->pRightChild, pTarget->nData);   
    }

}

void BinSortTree::Traversal(int nType)
{
    if (0 == nType)
    {
        //中序遍历二叉树
        InorderTraversal(m_pRoot);
    }
    else if (1 == nType)
    {
        LevelOrderTraversal(m_pRoot);
    }

}

void BinSortTree::InorderTraversal(Node *pNode)
{

    if (pNode == NULL)
    {
        return;
    }
    //先遍历左子树
    if (NULL != pNode->pLeftChild)
    {
        InorderTraversal(pNode->pLeftChild);
    }
    //访问根节点
    cout << pNode->nData << endl;
    //遍历右子树
    if (NULL != pNode->pRightChild)
    {

        InorderTraversal(pNode->pRightChild);
    }

}

//层序遍历二叉树
void BinSortTree::LevelOrderTraversal(Node *pNode)
{
    if (pNode == NULL)
    {
        return;
    }
    //层序遍历需要一个队列保存未访问节点,按从根层到底层的顺序边淋(从上到下,从左到右)
    queue<Node*> que;
    que.push(pNode);

    while (!que.empty())
    {
        //访问节点
        Node *p = que.front();
        que.pop();//出队列
        cout << p->nData << endl;//访问节点

        if (NULL != p->pLeftChild)
        {
            que.push(p->pLeftChild);
        }
        if (NULL != p->pRightChild)
        {
            que.push(p->pRightChild);
        }
    }
}

main.cpp

#include <iostream>
#include "BinSortTree.h"
using namespace std;

int main()
{
BinSortTree tree;
tree.Insert(10);
tree.Insert(1);
tree.Insert(11);
tree.Insert(11);
tree.Insert(-1);
tree.Insert(99);

cout << "*************中序遍历二叉树(删除前)**********" << endl;
tree.Traversal();

tree.Erase(10);
Node *pNode = tree.Find(10);
if (NULL != pNode)
{
  cout << "找到节点:" << pNode->nData << endl;
}
cout << "*************中序遍历二叉树(删除后)**********" << endl;
tree.Traversal();

//cout << "*************层序遍历二叉树**********" << endl;
//tree.Traversal(1);
return 0; 
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值