困扰我许久的项目终于写完了第一个正式版本,经过这几天对二叉搜索树的使用让我对这个数据结构有了更深刻的认识,今天我就来总结一下这个数据结构。
什么是二叉搜索树:二叉搜索树是一棵有以下性质的二叉树:1, 若左子树非空,则左子树上所有结点关键字均小于根结点的关键字值,2:若右子树非空,则右子树上所有结点关键字均大于根结点的关键字值,3: 左、右子树本身也分别是一棵二叉排序树。
认识了什么是二叉搜索树就然我们来到二叉搜索树的第一个操作:插入。为什么不先讲创建呢?其实二叉搜索树的创建就是将节点插入树中。我们先定义二叉搜索树的结构体:
struct tree{
struct xs data;
struct tree *lc,*rc;
};
根据定义我们将插入分成两种情况,1,当树根为空时,我们就直接将输入的数据用根节点存储,2,当根不为空时,我们要根据二叉搜索树的定义,当输入值大于当前根的值时就递归向右找叶子节点将其插入,当输入值小于当前根的值时就递归向左找叶子节点插入。代码如下:
void creatandadd(int x){
if(head==NULL){
head=(struct tree*)malloc(sizeof(struct tree));
head->data=x;
head->lc=NULL;
head->rc=NULL;
return ;
}else{
struct tree *q;
p=head;
while(p!=NULL){
q=p;
if(x>=p->data){
p=p->rc;
}else{
p=p->lc;
}
}
if(q->data>=x){
t=(struct tree*)malloc(sizeof(struct tree));
t->data=x;
t->lc=NULL;
t->rc=NULL;
q->lc=t;
}else{
t=(struct tree*)malloc(sizeof(struct tree));
t->data=x;
t->lc=NULL;
t->rc=NULL;
q->rc=t;
}
}
}
接下来第二个操作:查找。查找就相对简单,根据定义查找,若查找值大于当前节点就递归向右找,小于就递归向左找,这正是二叉搜索树查找速度快的原因,每一次查找都相当与一次二分查找,接下来是代码:
int find(int x){
p=head;
int step=1;
while(p!=NULL){
if(p->data>x){
p=p->lc;
step=2*step;
continue;
}
if(p->data<x){
p=p->rc;
step=2*step+1;
continue;
}
if(p->data==x){
return step;
}
}
return -1;
}
第三个操作:删除,这是二叉搜索树对复杂的一个操作,我们将其分成三种情况1:删除的节点为叶子节点时,这是最简单的情况直接将其父亲节点的对应子树指向空。2:删除的节点有左右子树的其中一棵,就要删除该节点并将其的左或右子树连接到原来的父节点上代替就行。第三种情况,被删除节点的左右子树都存在,我们要说一下二叉搜索树的另一个性质,对一棵二叉搜索树进行中序遍历,可以得到一个有序序列如图:
此时我们要删除其中的节点,要让原本的顺序不变,就要让他的直接前驱或直接后继去代替它,而他们分别位于节点左子树的最右边,右子树的最左边,如此交换二者的值再去删除后继或前驱节点就转变成了第二种情况。附上代码:
struct tree *D(struct tree *root,int x){
struct tree *fa=NULL,*p=NULL,*s=NULL;
p=root;
while(p->data.math!=x){
fa=p;
if(x>p->data.math){
p=p->rc;
}else if(x<p->data.math){
p=p->lc;
}
}
if(p->lc==NULL&&p->rc==NULL){
if(fa->lc==p){
fa->lc=NULL;
free(p);
}
if(fa->rc==p){
fa->rc=NULL;
free(p);
}
}else if(p->lc==NULL){
if(fa->lc==p){
fa->lc=p->rc;
free(p);
}
if(fa->rc==p){
fa->rc=p->rc;
free(p);
}
}else if(p->rc==NULL){
if(fa->lc==p){
fa->lc=p->lc;
free(p);
}
if(fa->rc==p){
fa->rc=p->lc;
free(p);
}
}else{
int t=0;
s=p->rc;
while(s->lc!=NULL){
s=s->lc;
}
t=s->data.math;
D(root1,s->data.math);
p->data.math=t;
}
}