二叉查找樹的插入和刪除詳解請看:http://blog.csdn.net/sysu_arui/article/details/7865864
前面詳細講解了二叉查找樹插入和刪除,現在給出完整的C++實現,代碼如下:
#include <cstdlib>
#include <iostream>
using namespace std;
template <typename T>
class BinarySearchTree
{
public:
BinarySearchTree() : root(NULL){}
BinarySearchTree(const BinarySearchTree& rhs) : root(NULL)
{
*this = rhs;
}
~BinarySearchTree()
{
makeEmpty();
}
//返回最大的元素值
const T& findMax()const
{
if(!isEmpty())
{
return findMax(root)->element;
}
}
//返回最小的元素值
const T& findMin()const
{
if(!isEmpty())
{
return findMin(root)->element;
}
}
//判斷是否包含給定元素
bool contains(const T& x)const
{
return contains(root,x);
}
//判斷二叉查找樹是否爲空
bool isEmpty()const
{
return root == NULL;
}
//中序輸出二叉查找樹
void printTree(ostream& out = cout)const
{
if(isEmpty())
{
out<<"Empty Tree"<<endl;
}
else
printTree(root,out);
}
//把二叉查找樹置空
void makeEmpty()
{
makeEmpty(root);
}
//插入給定元素
void insert(const T& x)
{
insert(root,x);
}
//刪除給定元素
void remove(const T& x)
{
remove(root,x);
}
//重載賦值運算符
const BinarySearchTree & operator=(const BinarySearchTree &rhs)
{
if(this != &rhs)
{
makeEmpty();
root = clone(rhs.root);
}
return *this;
}
private:
struct BinaryNode
{
T element;
BinaryNode * left;
BinaryNode * right;
BinaryNode(const T& elem, BinaryNode* lt=NULL, BinaryNode *rt=NULL)
:element(elem),left(lt),right(rt){}
};
BinaryNode *root; //根結點
//在以t爲根結點的樹中,插入元素x
void insert(BinaryNode* & t , const T& x)
{
if( t == NULL )
t = new BinaryNode( x, NULL, NULL );
else if(x < t->element)
insert(t->left,x);
else if(t->element < x)
insert(t->right,x);
else
; // 重複元素,不插入
}
//在以t爲根結點的樹中,刪除元素x
void remove(BinaryNode* & t , const T& x)
{
if(t == NULL)
return;
if(x < t->element)
remove(t->left,x);
else if(t->element < x)
remove(t->right,x);
else if(t->left && t->right) // 左右子女都存在
{
t->element = findMin(t->right)->element;//後繼
remove(t->right,t->element);
}
else
{
BinaryNode *oldNode = t;
t = (t->left) ? t->left : t->right;
delete oldNode;
}
}
// //遞歸查找最小結點
// BinaryNode * findMin(BinaryNode *t)const
// {
// if(t==NULL)
// return NULL;
// if(t->left==NULL)
// return t;
// return findMin(t->left);
// }
//非遞歸查找最小結點
BinaryNode * findMin(BinaryNode *t)const
{
if(t)
{
while(t->left)
{
t = t->left;
}
}
return t;
}
// //遞歸查找最大結點
// BinaryNode * findMax(BinaryNode *t)const
// {
// if(t==NULL || t->right==NULL)
// return t;
// return findMax(t->right);
// }
//非遞歸查找最大結點
BinaryNode * findMax(BinaryNode *t)const
{
if(t)
{
while(t->right)
{
t = t->right;
}
}
return t;
}
// //遞歸查找是否包含給定元素
// bool contains(BinaryNode *t, const T& x)const
// {
// if(t)
// {
// if(x < t->element)
// return contains(t->left,x);
// else if(t->elment < x)
// return contains(t->right,x);
// else
// return true;
// }
// return false;
// }
//非遞歸查找是否包含給定元素
bool contains(BinaryNode *t, const T& x)const
{
while(t)
{
if(x < t->element)
t = t->left;
else if(t->element < x)
t = t->right;
else return true;
}
return false;
}
//中序遍歷-遞歸
void printTree(BinaryNode* t, ostream& out)const
{
if(t)
{
printTree(t->left,out);
out<<t->element<<" ";
printTree(t->right,out);
}
}
//刪除二叉查找樹
void makeEmpty(BinaryNode* & t)
{
if(t)
{
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
t = NULL;
}
}
//複製二叉查找樹
BinaryNode * clone(const BinaryNode* &t)const
{
if(t==NULL)
return NULL;
return new BinaryNode(t->element,clone(t->left),clone(t->right));
}
};
int main(int argc, char *argv[])
{
BinarySearchTree<int> bst;
int x;
while(cin>>x && x)//以0作爲輸入結束
{
bst.insert(x);
}
cout<<"After insert:"<<endl;
bst.printTree();
cout<<endl<<"Min: "<<bst.findMin()<<endl;
cout<<"Max: "<<bst.findMax()<<endl<<endl;
cout<<"input the elements you want to remove:"<<endl;
while(cin>>x && x)
{
bst.remove(x);
}
cout<<"After remove :"<<endl;
bst.printTree();
cout<<endl<<endl;
cout<<"After clear :"<<endl;
bst.makeEmpty();
bst.printTree();
cout<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
注:
(1)該類爲一個模板類,結點元素數據域類型可以是基本數據類型,也可以是複雜類對象。當使用複雜類對象時,類必須重載了賦值運算符和比較運算符,在上面的代碼中,只用到了<比較運算符,所以類比較運算符至少得重載<。
(2)上面的成員函數有些同時給出了遞歸實現和非遞歸實現,有的只給出了遞歸實現,遞歸的好處是邏輯清晰,代碼簡潔,但是效率低下。其實弄清楚了原理,遞歸和非遞歸之間轉換就很簡單了。
(3)對於在一個含有n個元素的序列中查找給定元素的問題,如果採用簡單的順序查找,複雜度爲O(n)。採用二叉查找樹進行查找,如果樹高爲h,則複雜度爲O(h)。對於含n個結點的二叉樹,樹的平均高度爲h=「log(n+1)|。但是當給定的序列基本有序時,樹的高度h接近n,此時時間複雜度幾乎爲O(n)。如當輸入爲遞增序列時,查找樹爲一棵沒有左子樹的單支樹,樹高爲n。爲了儘可能的降低樹的高度,減少檢索次數,我們可以把輸入序列進行隨機化,構造一棵隨機化的二叉查找樹。或則採用其他的平衡查找樹,如紅黑樹,AVL樹等,後面會一一講解。
二叉查找樹的插入和刪除詳解請看:http://blog.csdn.net/sysu_arui/article/details/7865864
參考資料:
Data Structures and Algorithm Analysis in C++(third editon) (數據結構與算法分析C++描述,第3版 )