二叉搜索树又称为二叉排序树,它为一棵空树,或者是一棵左子树所有节点的值比根节点小,右子树所有节点的值比根节点大的一棵树。
性质:
①.二叉搜索树中,最左边的结点值最小,最右边的结点值最大
②中序遍历一棵二叉搜索树,所有节点的值是按顺序排列的构造一棵二叉搜索树时,比较插入结点的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;
}