二叉排序樹(Binary Sort Tree)又稱二叉尋找樹,它的特點是:
(1)若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
(2)若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
(3)左、右子樹也分別為二叉排序樹;
但你看到定義可能會奇怪,如果出現相等元素咋整啊.這裡我們就假設右子樹的結點值大於或等於根結點得了.
在這裡我們實現二叉樹的如下簡易功能:(二叉樹結點類為BTreeNode<T>)
void Insert(T val); //往二叉樹中插入資料,自然要保證插入資料後仍然是二叉樹
BTreeNode<T>* Search(T val); //尋找值為val的結點
BTreeNode<T>* SearchMinVal(); //尋找值最小的結點
BTreeNode<T>* SearchMaxVal();//尋找值最大的結點
void Delete(T val); //刪除任意節點
1.先定義一個二叉樹的結點類
template<class T>
class BTreeNode{
public:
T val;
BTreeNode<T>* left; //指向左孩子的指標
BTreeNode<T>* right;
BTreeNode<T>* parent; //指向父結點的指標
BTreeNode(T tVal){
val = tVal;
left = right = parent = NULL;
}
bool operator==(BTreeNode<T>* bt){ //重載操作符比較兩結點是否相等
return bt.val == val ? true: false;
}
};
2.定義二叉尋找樹的類BSortTree
#include "BTreeNode.h"
template<class T>
class BSortTree{
private:
BTreeNode<T>* root; //根結點指標
int size; //樹中元素總個數
public:
BSortTree(void){
root = NULL;
size = 0;
}
~BSortTree(void){}
int Size() { return size;}
void Insert(T val){ //插入結點元素
if(root == NULL){ //樹為空白
BTreeNode<T>* pNode = new BTreeNode<T>(val);
root = pNode;
size++;
return;
}
InsertTree(root, val); //樹不為空白時插入元素
}
BTreeNode<T>* Search(T val){ //尋找結點
return SearchTree(root, val);
}
BTreeNode<T>* SearchMinVal(){ //尋找最小值元素
SearchTreeMinVal(root);
}
BTreeNode<T>* SearchMaxVal(){ //尋找最大值元素
SearchTreeMaxVal(root);
}
void Delete(T val){ //刪除任意結點
DeleteTreeNode(root, val);
}
private:
//刪除節點分4種情況
//1.如果是葉子,則直接刪除
//2.如果只有左子樹,則刪除結點後左子樹上移即可
//3.如果只有右子樹,則刪除結點後右子樹上移即可
//4.如果左右子樹都有,則尋找要刪除結點(p)的左子樹中的最大結點(m),把m的結點值賦給p,然後刪除m.
void DeleteTreeNode(BTreeNode<T>* pRoot, T val){ //刪除結點
BTreeNode<T>* node = Search(val); //要刪除的結點
if(node == NULL) //要刪除的結點不存在
return;
//1.被刪結點是葉子,直接刪
if(node->left==NULL && node->right==NULL){
if(node->parent == NULL){ //只有一個結點的樹
size = 0;
root = NULL;
}
else if(node->parent->left == node)//被刪結點是左孩子
node->parent->left = NULL;
else //結點是右孩子
node->parent->right = NULL;
delete node;
size--;
return;
}
//2.被刪結點只有左子樹
if(node->left !=NULL && node->right==NULL){
node->left->parent = node->parent;
if(node->parent == NULL) //被刪結點是根結點
root = node->left;
else if(node->parent->left == node)//被刪結點是左孩子
node->parent->left = node->left;
else //被刪結點是右孩子
node->parent->right = node->right;
delete node;
size--;
return;
}
//3.被刪結點只有右子樹
if(node->right !=NULL && node->left==NULL){
node->right->parent = node->parent;
if(node->parent == NULL) //被刪結點是根結點
root = node->right;
else if(node->parent->left == node)//被刪結點是左孩子
node->parent->left = node->left;
else //被刪結點是右孩子
node->parent->right = node->right;
delete node;
size--;
return;
}
//4.被刪結點左右孩子都有
if(node->left !=NULL && node->right != NULL){
BTreeNode<T>* replaceNode = SearchTreeMinVal(node->right); //也可以替換成尋找左子樹最大值
node->val = replaceNode->val;
DeleteTreeNode(root, replaceNode->val);
}
}
void InsertTree(BTreeNode<T>* pRoot,T val)
{
BTreeNode<T>* pNode = new BTreeNode<T>(val);
if(pRoot->left == NULL && val < pRoot->val){
pRoot->left = pNode;
pNode->parent = pRoot;
size++;
return;
}
if(pRoot->right == NULL && val >= pRoot->val){
pRoot->right = pNode;
pNode->parent = pRoot;
size++;
return;
}
if(val < pRoot->val)
InsertTree(pRoot->left,val);
else
InsertTree(pRoot->right,val);
}
BTreeNode<T>* SearchTree(BTreeNode<T>* pRoot,T val){
if(pRoot == NULL)
return NULL;
else if(val == pRoot->val)
return pRoot;
else if(val < pRoot->val)
return SearchTree(pRoot->left,val);
else
return SearchTree(pRoot->right, val);
}
BTreeNode<T>* SearchTreeMinVal(BTreeNode<T>* pRoot){
if(pRoot==NULL)
return NULL;
else if(pRoot->left == NULL)
return pRoot;
else
return SearchTreeMinVal(pRoot->left);
}
BTreeNode<T>* SearchTreeMaxVal(BTreeNode<T>* pRoot){
if(pRoot==NULL)
return NULL;
else if(pRoot->right == NULL)
return pRoot;
else
return SearchTreeMinVal(pRoot->right);
}
};