二叉搜索樹:又稱二叉排序樹,他有三個特點:
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;
}