二叉搜索树:其又叫做二叉排序树,它或是一个空树,或是具有以下性质:
1、若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。
2、若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
3、它的左右子树也分别为二叉搜索树。
如下图所示的二叉搜索树:
给出具体的树的节点的结构如下:(左子树,右子树,key值,value值)
template<class k,class v>
struct BSTreeNode
{
BSTreeNode(const k&key, const v&value)
:_pLeft(NULL)
, _pRight(NULL)
, _key(key)//要查找的值
, _value(value)//数组的下标
{}
BSTreeNode<k, v>*_pLeft;
BSTreeNode<k, v>*_pRight;
k _key;
v _value;
};
下面来看看二叉搜索树的具体操作:
先来看看查找操作:
具体的操作代码为:
pNode Find(const k&key)//查找函数
{
pNode pcur = _pRoot;
while (pcur)
{
if (key == pcur->_key)
{
return pcur;
}
else if (pcur->_key > key)
{
pcur = pcur->_pLeft;
}
else
{
pcur = pcur->_pRight;
}
}
return NULL;
}
插入操作:
1.在向二叉搜索树中插入新元素时,先要检测这个元素是否在树中已经存在。若已经存在,则不进行插入,返回false;
2.若需插入的元素小于根节点的key,则继续走到其左子树。
3.若需插入的元素大于根节点的key,则继续走到其右子树。
具体的操作代码如下:
bool insert(const k&key, const v&value)//插入
{
if (_pRoot == NULL)
{
_pRoot = new Node(key, value);
return true;
}
pNode pcur = _pRoot;
pNode parent = NULL;
//1.找到待插入的位置
while (pcur)
{
if (key < pcur->_key)
{
parent = pcur;
pcur = pcur->_pLeft;
}
else if (key > pcur->_key)
{
parent = pcur;
pcur = pcur->_pRight;
}
else
return false;
}
//2.插入新节点
pcur = new Node(key, value);
if (key < parent->_key)
{
parent->_pLeft = pcur;
}
if (key > parent->_key)
{
parent->_pRight = pcur;
}
}
删除操作:
二叉搜索树的删除操作较为复杂,具体分为四种情况:
1.要删除的节点无左右孩子。
2.要删除的节点只有左孩子。
3.要删除的节点只有右孩子。
4.要删除的节点有左右孩子。
因为情况一可以归结到情况二、三中,所以我们先从情况二开始看。
情况三与情况二类似。不展开具体的讨论。
情况四:
删除的具体代码实现为:
bool remove(const k&key)//删除
{
pNode parent = NULL;
pNode pcur = _pRoot;
//1.找到待删除的节点
while (pcur)
{
if (pcur->_key > key)
{
parent = pcur;
pcur = pcur->_pLeft;
}
else if (pcur->_key < key)
{
parent = pcur;
pcur = pcur->_pRight;
}
else
{
break;
}
}
if (pcur)
{
if (pcur->_pLeft == NULL)//只有右子树
{
if (pcur != _pRoot)
{
if (parent->_pLeft == pcur)
parent->_pLeft = pcur->_pRight;
else
parent->_pRight = pcur->_pRight;
}
else
_pRoot = pcur->_pRight;
delete pcur;
pcur = NULL;
}
else if (pcur->_pRight == NULL)//只有左子树
{
if (pcur != _pRoot)
{
if (parent->_pLeft == pcur)
parent->_pLeft = pcur->_pLeft;
else
parent->_pRight = pcur->_pRight;
}
else
_pRoot = pcur->_pLeft;
delete pcur;
pcur = NULL;
}
else //左右子树存在
{
pNode parent = pcur;
pNode pDel = pcur->_pRight;//找到其右子树中序下的第一个节点
while (pDel->_pLeft)//找到其左子树
{
parent = pDel;
pDel = pDel->_pLeft;
}
pcur->_key = pDel->_key;
pcur->_value = pDel->_value;
if (parent->_pLeft == pDel)
parent->_pLeft = pDel->_pLeft;
else
parent->_pRight = pDel->_pRight;
delete pDel;
pDel = NULL;
}
return true;
}
return false;
}
//注:若要删除的节点无孩子节点,可以归结到第二三种情况中。
查找最小的数:即为一直在左子树中寻找,具体实现为:
k MinData()//找寻最左边小的数
{
assert(_pRoot);
pNode pcur = _pRoot;
while (pcur->_pLeft)
{
pcur = pcur->_pLeft;
}
return pcur->_key;
}
查找最大的数:
k maxData()//找寻最右边大的数
{
assert(_pRoot);
pNode pcur = _pRoot;
while (pcur->_pRight)
{
pcur = pcur->_pRight;
}
return pcur->_key;
}
完整的代码如下:
#include<iostream>
#include<assert.h>
using namespace std;
template<class k,class v>
struct BSTreeNode
{
BSTreeNode(const k&key, const v&value)
:_pLeft(NULL)
, _pRight(NULL)
, _key(key)//要查找的值
, _value(value)//数组的下标
{}
BSTreeNode<k, v>*_pLeft;
BSTreeNode<k, v>*_pRight;
k _key;
v _value;
};
template<class k,class v>
class BSTree
{
public:
typedef BSTreeNode<k, v>Node;
typedef BSTreeNode<k, v>* pNode;
BSTree()
:_pRoot(NULL)
{}
void _CopyBinaryTee(pNode *pRoot)//创建二叉搜索树
{
pRoot = new Node(pRoot->_key, pRoot->_value);
_CopyBinaryTee(&((*pRoot)->_pLeft));
_CopyBinaryTee(&((*pRoot)->_pRight));
}
BSTree<k, v>& operator = (const BSTree<k, v>& bst)
{
if (this != &bt)
{
_DestoryBinaryTree(_pRoot);
_pRoot = _CopyBinaryTree(bt._pRoot);
}
return *this;
}
void _DestoryBinaryTree(pNode pRoot)//销毁空间
{
if (pRoot)
{
_DestoryBinaryTree(pRoot->_pLeft);
_DestoryBinaryTree(pRoot->_pRight);
delete pRoot;
pRoot = NULL;
}
}
bool insert(const k&key, const v&value)//插入
{
if (_pRoot == NULL)
{
_pRoot = new Node(key, value);
return true;
}
pNode pcur = _pRoot;
pNode parent = NULL;
//1.找到待插入的位置
while (pcur)
{
if (key < pcur->_key)
{
parent = pcur;
pcur = pcur->_pLeft;
}
else if (key > pcur->_key)
{
parent = pcur;
pcur = pcur->_pRight;
}
else
return false;
}
//2.插入新节点
pcur = new Node(key, value);
if (key < parent->_key)
{
parent->_pLeft = pcur;
}
if (key > parent->_key)
{
parent->_pRight = pcur;
}
}
pNode Find(const k&key)//查找函数
{
pNode pcur = _pRoot;
while (pcur)
{
if (key == pcur->_key)
{
return pcur;
}
else if (pcur->_key > key)
{
pcur = pcur->_pLeft;
}
else
{
pcur = pcur->_pRight;
}
}
return NULL;
}
k MinData()//找寻最左边小的数
{
assert(_pRoot);
pNode pcur = _pRoot;
while (pcur->_pLeft)
{
pcur = pcur->_pLeft;
}
return pcur->_key;
}
k maxData()//找寻最右边大的数
{
assert(_pRoot);
pNode pcur = _pRoot;
while (pcur->_pRight)
{
pcur = pcur->_pRight;
}
return pcur->_key;
}
void Inorder()
{
return _Inorder(_pRoot);
}
void _Inorder(pNode pRoot)//中序
{
if (pRoot)
{
_Inorder(pRoot->_pLeft);
cout << "<" << pRoot->_key << "," << pRoot->_value << ">" << endl;
_Inorder(pRoot->_pRight);
}
}
bool remove(const k&key)//删除
{
pNode parent = NULL;
pNode pcur = _pRoot;
//1.找到待删除的节点
while (pcur)
{
if (pcur->_key > key)
{
parent = pcur;
pcur = pcur->_pLeft;
}
else if (pcur->_key < key)
{
parent = pcur;
pcur = pcur->_pRight;
}
else
{
break;
}
}
if (pcur)
{
if (pcur->_pLeft == NULL)//只有右子树
{
if (pcur != _pRoot)
{
if (parent->_pLeft == pcur)
parent->_pLeft = pcur->_pRight;
else
parent->_pRight = pcur->_pRight;
}
else
_pRoot = pcur->_pRight;
delete pcur;
pcur = NULL;
}
else if (pcur->_pRight == NULL)//只有左子树
{
if (pcur != _pRoot)
{
if (parent->_pLeft == pcur)
parent->_pLeft = pcur->_pLeft;
else
parent->_pRight = pcur->_pRight;
}
else
_pRoot = pcur->_pLeft;
delete pcur;
pcur = NULL;
}
else //左右子树存在
{
pNode parent = pcur;
pNode pDel = pcur->_pRight;//找到其右子树中序下的第一个节点
while (pDel->_pLeft)//找到其左子树
{
parent = pDel;
pDel = pDel->_pLeft;
}
pcur->_key = pDel->_key;
pcur->_value = pDel->_value;
if (parent->_pLeft == pDel)
parent->_pLeft = pDel->_pLeft;
else
parent->_pRight = pDel->_pRight;
delete pDel;
pDel = NULL;
}
return true;
}
return false;
}
//注:若要删除的节点无孩子节点,可以归结到第二三种情况中。
~BSTree()
{
_DestoryBinaryTree(_pRoot);
}
private:
pNode _pRoot;
};
int main()
{
int arr[] = {5,3,4,1,7,8,2,6,0,9};
BSTree<int, int>bst;
for (int i = 0; i <10; i++)
{
bst.insert(arr[i], i);
}
bst.Inorder();
cout << bst.Find(3)->_value << endl;
cout << endl;
bst.remove(7);
bst.Inorder();
cout << bst.MinData() << endl;
cout << bst.maxData() << endl;
system("pause");
return 0;
}
验证结果为: