先提几个问题,如下:
1.还记得二分查找吗?(对分查找)它是适合于操作什么类型的数据?
2.二叉树,二叉完全树,二叉排序树,堆排序,分别是什么?它们是用来干什么?
3.为什么二叉树要用中序遍历,而不是前或者后序遍历?
好了,这里我给出了,二叉排序树的插入,删除,输出,与查找的用例,具体看代码:
#include<iostream>
using namespace std;
template <class T>
struct BSnode{
T d;
BSnode* lchild;
BSnode* rchild;
};
template <class T>
class BS_Tree{
private:
BSnode<T>*BT;
public:
BS_Tree(){BT=NULL;return;}
void insert_BS_Tree(T);
int delete_BS_Tree(T);
BSnode<T>* serch_BS_Tree(T);
void intrav_BS_Tree();
};
template <class T>
void BS_Tree<T>::intrav_BS_Tree(){
BSnode<T>*p;
p=BT;
intrav(p);
return;
}
template <class T>
static intrav(BSnode<T> *p){
if(p!=NULL){
intrav(p->lchild);
cout<<p->d<<endl;
intrav(p->rchild);
}
return 0;
}
template <class T>
void BS_Tree<T>::insert_BS_Tree(T x){
BSnode<T> *p,*q;
p=new BSnode<T>;
p->d=x;
p->lchild=NULL;p->rchild=NULL;
q=BT;
if(q==NULL) BT=p;
else
{
while((q->lchild!=p)&&(q->rchild!=p)){
if(x<q->d){if(q->lchild!=NULL) q=q->lchild;
else q->lchild=p;
}
else
{
if(q->rchild!=NULL) q=q->rchild;
else q->rchild=p;
}
}
}
return;
}
template <class T>
int BS_Tree<T>::delete_BS_Tree(T x){
BSnode<T> *p,*q,*t,*s;
int flag;
p=BT;q=NULL;flag=0;
while((p!=NULL)&&(flag==0)){
if(p->d==x) flag=1;
else if(x<p->d){q=p;p=p->lchild;}
else
{q=p;p=p->rchild;}
}
if(p==NULL){cout<<"not found"<<endl; return flag;}
flag=1;
if((p->lchild==NULL)&&(p->rchild==NULL)){
if(p==BT) BT=NULL;
else if(p==q->lchild) q->lchild=NULL;
else q->rchild=NULL;
delete p;
}
else if((p->lchild==NULL)||(p->rchild==NULL)){
if(p==BT){
if(p->lchild==NULL) BT=p->rchild;
else BT=p->lchild;
}
else{
if((p==q->lchild)&&(p->lchild!=NULL))
q->lchild=p->lchild;
else if((p==q->lchild)&&(p->rchild!=NULL))
q->lchild=p->rchild;
else if((p==q->rchild)&&(p->lchild!=NULL))
q->rchild=p->lchild;
else
q->rchild=p->rchild;
}
delete p;
}
else{
t=p;
s=t->lchild;
while(s->rchild!=NULL){
t=s;s=s->rchild;
}
p->d=s->d;
if(t==p)
p->lchild=s->lchild;
else
t->rchild=s->lchild;
delete s;
}
return flag;
}
template <class T>
BSnode<T>*BS_Tree<T>::serch_BS_Tree(T x){
BSnode<T> *p=NULL;
int flag;
p=BT;flag=0;
while((p!=NULL)&&(flag==0)){
if(p->d==x) flag=1;
else if(x<p->d) p=p->lchild;
else p=p->rchild;
}
if(p==NULL){cout<<"not found";return p;}
return p;
}
具体调用这些操作的实例,看下面:
#include"BS_Tree.h"
int main(){
int k;
int d[12]={04,18,13,79,33,45,06,23,35,12,34,76};
BS_Tree<int> b;
for(k=0;k<12;k++)
b.insert_BS_Tree(d[k]);
cout<<"the sort element:"<<endl;
b.intrav_BS_Tree();
for(k=0;k<6;k++)
b.delete_BS_Tree(d[k]);
cout<<"after the delete:"<<endl;
b.intrav_BS_Tree();
cout<<"the serch result:"<<endl;
for(k=0;k<12;k++)
cout<<b.serch_BS_Tree(d[k])<<endl;
return 0;
}
具体,最后的实验结果,我就不多说了,不过,关于,代码中的一些操作说几点:
关于中序遍历:
这个在前面的二叉树遍历中就讲过了,而这里,二叉排序树的排序,就是,这个中序,所以很简单不多说。
关于插入:
一个二叉树的建立,就是把节点一个一个插入就完成了。
千万记住:插入的每个点,其实,,,都是在叶子结点处,不信,你自己看看。明白了这个,插入就ok了
关于删除:
这个就比较麻烦了,因为情况有3种,这个和你是二叉树是有关系的,那么:
1.自己是叶子结点
好了,删除呗,没啥好商量的,它的父亲处理一下,令为NULL就好了
2.自己有一个单子树
那么它的孩子们就跟它的父亲,父亲在爷爷的左边,孙子就去左边,父亲在爷爷的右边,孙子就去爷爷的右边,不管你是你父亲的左边还是右边
3.自己有2个孩子
那这就比较麻烦了,我给出的这个例子的思路是,判断这个结点的左结点的右子树空吗?空,那就把你孩子的值,给你,然后再把你挤掉,否则,那就找左结点的右子树的右子树,直到这个点是叶子节点,此时,让这个结点代替你,这个结点的孩子代替它。
也许说的有点乱,直接点就是说,让这个点的要么前驱,要么后继,代替它,然后保持二叉树的完整。
至于实现,那么就有很多的具体办法了。仁者见仁 。