二叉搜索树:又称二叉排序树,他有三个特点:
1、若它的左子树不为空,那么它的左子树中所有节点的值都小于根结点的值
2、若它的右子树不为空,那么它的右子树的所有节点的值都大于根结点的值
3、它的左右子树也是二叉搜索树
那么现在我们就来给出一个二叉搜索树,我们来观察一下,看看能发现什么。
首先我们可以根据他的性质可以分析出,最左边的结点是最小的,而最右边的结点是最大的,这样就给出了一个求最小结点和最大结点的方法。
当我们用中序遍历的方式来遍历这个二叉树的时候,会发现什么:0123456789
它是有序的,也就是说,二叉搜索树在中序遍历下是有序的,这个很重要。
了解完了这些之后,我们在来看一下它的实现过程吧
首先是插入操作,要想插入,我们必须构建一个结构体来创建它的结点:
template<class K, class V>
struct BSTNode
{
BSTNode(const K& key, const V& value)
: _pLeft(NULL)
, _pRight(NULL)
, _key(key)
, _value(value)
{}
BSTNode<K, V>* _pLeft;
BSTNode<K, V>* _pRight;
K _key;
V _value;
};
然后就是插入和删除操作了,具体是怎么实现呢,我们来看一下过程分析:
下面是总体的代码:包括递归和非递归两种实现的方法,及测试用例
#include<iostream>
using namespace std;
template<class K, class V>
struct BSTNode
{
BSTNode(const K& key, const V& value)
: _pLeft(NULL)
, _pRight(NULL)
, _key(key)
, _value(value)
{}
BSTNode<K, V>* _pLeft;
BSTNode<K, V>* _pRight;
K _key;
V _value;
};
//// 非递归版本
//template<class K, class V>
//class BSTree
//{
// typedef BSTNode<K, V> Node;
//public:
// BSTree()
// : _pRoot(NULL)
// {}
//
// //BSTree(const BSTree& bst);
// //BSTree<K, V>& operator=(const BSTree<K, V>& bst);
// //~BSTree();
//
//
// bool Insert(const K& key, const V& value)
// {
// return _Insert(_pRoot, key, value);
// }
//
// Node* Find(const K& key)
// {
// return _Find(_pRoot, key);
// }
//
// bool Remove(const K& key)
// {
// return _Remove(_pRoot, key);
// }
//
// //二叉搜索树的中序遍历是有序的
// void InOrder()
// {
// cout << "InOrder: ";
// _InOrder(_pRoot);
// cout << endl;
// }
//
// const K& GetMaxKey()const;
// const K& GetMinKey()const;
//
//protected:
// //中序遍历
// void _InOrder(Node* pRoot)
// {
// if (pRoot)
// {
// _InOrder(pRoot->_pLeft);
// cout << pRoot->_key << " ";
// _InOrder(pRoot->_pRight);
// }
// }
//
// //插入
// bool _Insert(Node* & pRoot, const K& key, const V& value)
// {
// if (pRoot == NULL)//如果树是空的,那么直接插入,并返回true
// {
// pRoot = new Node(key, value);
// return true;
// }
//
// Node* pCur = pRoot;
// Node*parent = NULL;
//
// //开始找插入位置
// while (pCur)
// {
// if (key < pCur->_key)//如果要插入的Key要小于当前结点的key,那么去左子树中继续遍历
// {
// parent = pCur;
// pCur = pCur->_pLeft;
// }
// else if (key>pCur->_key)//如果要插入的Key要大于当前结点的key,那么去右子树中继续遍历
// {
// parent = pCur;
// pCur = pCur->_pRight;
// }
// else//否则,说明这个KaKey已存在,那么久不用插入了,返回false
// return false;
// }
//
// //开始插入,判断这个结点是其双亲结点的左还是右
// pCur = new Node(key, value);
// if (key < parent->_key)
// parent->_pLeft = pCur;
// else
// parent->_pRight = pCur;
//
// return true;//不要忘了,最后返回true
// }
//
// Node* _Find(Node* pRoot, 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;
// }
// //如果循环结束还没有找到,返回NULL
// return NULL;
// }
//
// bool _Remove(Node*& pRoot, const K& key)
// {
// //1、如果树为空,那么返回false
// if (pRoot == NULL)
// return false;
//
// //2、如果树只有一个结点,且key和要删除的key相等,那么直接删除
// if (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL&&pRoot->_key == key)
// {
// delete pRoot;
// pRoot = NULL;
// return true;
// }
//
// //3、普通情况,先将待删除结点找到,之后,又分为四种情况
// Node* pCur = pRoot;
// Node* parent = NULL;
// while (pCur)
// {
// if (key < pCur->_key)
// {
// parent = pCur;
// pCur = pCur->_pLeft;
// }
// else if (key>pCur->_key)
// {
// parent = pCur;
// pCur = pCur->_pRight;
// }
// else//找到,退出循环
// break;
// }
//
// if (pCur)
// {
// //没有左孩子
// if (pCur->_pLeft == NULL)
// {
// if (pCur != pRoot)
// {
// if (parent->_pRight == pCur)
// parent->_pRight = pCur->_pRight;
// else
// parent->_pLeft = pCur->_pRight;
// }
// else
// pRoot = pCur->_pRight;
// }
//
// //没有右孩子
// else if (pCur->_pRight == NULL)
// {
// if (pCur != pRoot)
// {
// if (parent->_pLeft == pCur)
// parent->_pLeft = pCur->_pLeft;
// else
// parent->_pRight = pCur->_pLeft;
// }
// else
// pRoot = pCur->_pLeft;
// }
//
// //左右孩子都有
// else
// {
// parent = pCur;
// Node* fio = pCur->_pRight;//找到右子树中,中序遍历下的第一个结点
// while (fio->_pLeft)
// {
// parent = fio;
// fio = fio->_pLeft;
// }
//
// pCur->_key = fio->_key;
// pCur->_value = fio->_value;
//
// if (parent->_pLeft == fio)
// parent->_pLeft = fio->_pRight;
// else
// parent->_pRight = fio->_pRight;
//
// pCur = fio;
// }
//
// //所有的情况都讨论完,删除结点,并返回true
// delete pCur;
// pCur = NULL;
// return true;
// }
// return false;
// }
//
//protected:
// Node* _pRoot;
//};
// 递归版本
template<class K, class V>
class BSTree
{
typedef BSTNode<K, V> Node;
public:
BSTree()
: _pRoot(NULL)
{}
//BSTree(const BSTree& bst);
//BSTree<K, V>& operator=(const BSTree<K, V>& bst);
//~BSTree();
bool Insert(const K& key, const V& value)
{
return _Insert(_pRoot, key, value);
}
Node* Find(const K& key)
{
return _Find(_pRoot, key);
}
bool Remove(const K& key)
{
return _Remove(_pRoot, key);
}
void InOrder()
{
cout << "InOrder: ";
_InOrder(_pRoot);
cout << endl;
}
protected:
bool _Insert(Node* & pRoot, const K& key, const V& value)
{
if (pRoot == NULL)
{
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;
}
Node* _Find(Node* pRoot, const K& key)
{
if (pRoot == NULL)
return NULL;
if (key < pRoot->_key)
return _Find(pRoot->_pLeft, key);
else if (key>pRoot->_key)
return _Find(pRoot->_pRight, key);
else
return pRoot;
}
bool _Remove(Node*&root, const K& key)
{
if (root == NULL)
return false;
if (root->_key < key)
return _Remove(root->_pRight, key);
else if (root->_key > key)
return _Remove(root->_pLeft, key);
else
{
Node* del = root;
if (root->_pLeft == NULL)
root = root->_pRight;
else if (root->_pRight == NULL)
root = root->_pLeft;
else
{
Node* minright = root; //寻找右树的最左结点进行key值的交换
minright = root->_pRight;
while (minright->_pLeft)
minright = minright->_pLeft;
root->_key = minright->_key;
del = minright;
}
delete del;
return true;
}
}
void _InOrder(Node* pRoot)
{
if (pRoot)
{
_InOrder(pRoot->_pLeft);
cout << pRoot->_key << " ";
_InOrder(pRoot->_pRight);
}
}
protected:
Node* _pRoot;
};
void FunTest()
{
int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
BSTree<int, int> bst;
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
bst.Insert(a[i], i);
}
bst.InOrder();
if (bst.Find(2))
cout << bst.Find(2)->_key << endl;
bst.Remove(3);
bst.InOrder();
bst.Remove(5);
bst.InOrder();
bst.Remove(6);
bst.InOrder();
bst.Remove(8);
bst.InOrder();
}
int main()
{
FunTest();
return 0;
}