二叉查找树的插入和删除详解请看: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版 )