二叉搜索树
参考大话数据结构和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
*/