最近在研究数据结构这本书,自己动手实现的一个二叉查找排序树的类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;
}
517

被折叠的 条评论
为什么被折叠?



