15二叉检索树
检索树
检索树的定义:
二叉检索树(或二叉排序树,二叉有序树)的简称,任一结点a,其左子树中结点的值均小于或等于a,右子树上结点值均大于a(左小右大)。
性质:中序序列是递增的有序序列。
1.检索树的构建方法:
创建一颗空树,通过遍历,进行有序插入,按照左小右大的原则。
检索树的构建算法:
Bptr creat( )
{ Bptr root; element_type x;
root=NULL; //开始时树为空
scanf("%d",&x); //读入元素序列
while(x!=ZERO) //ZERO是输入结束标记
{
insert(x,root); //插入x
scanf("%d",&x); //读入下一个元素
}
return root; //构造完毕,返回根结点指针
}
2.检索树的查找方法:
从根结点起,将要找的结点x与当前结点a比较:
如果遇到空树,表明x不在树中(查找失败)
若x=a,找到x (查找成功) ;
若x<a,则递归地查找左子树;
若x>a,则递归地查找右子树;
查找算法:
Bptr search(element_type x,Bptr p)
{
if (p==NULL)
return NULL; //遇到空树
if (x==p->data)
return p; //找到x
if (x<p->data)
return search(x, p->Lson); //递归向左
else
return search(x, p->Rson); //递归向右
}
主调语句: p=search(x,root);
3. 检索树的插入方法:
从根结点起,将要插入的元素x与当前的结点比较,
如果x小于或等于当前结点值,就向左搜索;
如果x大于当前结点值,就向右搜索;
直至遇到空结点,就将x作为一片新叶插在这个空
位置上
插入算法:
void insert(element_type x, Bptr &p)
{
if (p==NULL) //遇到空树
{
p=new Bnode; //申请新结点
p->data=x; //置新结点的值域
p->Lson=p->Rson=NULL; //新结点作叶子
return; //插入完毕,返回
} //否则,尚未找到插入点,继续查找.
if(x<=p->data)
insert(x,p->Lson); //递归的向左
else
insert(x,p->Rson); //递归的向右
}
主调语句为: insert( x, root);
检索树的删除方法:
要点:如何接好断枝,并保持“左小右大”
大体步骤如下:
步骤1)先用查找的方法找到要删除的结点x,并记住x的父亲f,再根据下列几种不同情况作出处理。
步骤2)若x是叶,只要把f指向x的那个链域(Lson或Rson)置空,就删除了x。
步骤3)若x只有一个儿子,只要将f指向x的那条链域(Lson或Rson)改为指向x的那个唯一的儿子。
步骤4)若x有两个儿子,就要找到x的中序前驱y,用y代替x,并删除y。这里“代替”指的是将结点y的值域复制到结点x中。
带监督元结点检索树的删除算法;
#define SUCC 1
#define NOTFOUND 0
根结点带带无穷小监督元
int deleteT(element_type x, Bptr root)
{
Bptr f,p,q,s,r;
p=NULL; //p将指向要删除结点
f=root; // f的初值指向虚根
q=root->Rson; //q搜索指针
while(q!=NULL) //循环查找x
{
if(x==q->data)
{
p=q;
q=NULL;} //找到x
else//没找到x后,继续搜索
if(x<q->data)
{
f=q;
q=q->Lson;
} //向左搜索
else
{
f=q;
q=q->Rson;
} //向右搜索
}
if(p==NULL)
return NOTFOUND; //没找到x
// 以下是找到x(p指向x)后的具体删除操作步骤
if (p->Rson==NULL) // p无右儿子,用左儿子代替p
{ if(p==f->Lson)
{
f->Lson=p->Lson;
delete p;
}
else
{
f->Rson=p->Lson;
delete p;
}
}
else
{
if (p->Lson==NULL) //p无左儿子,用右儿子代替p
{
if (p==f->Lson)
{
f->Lson=p->Rson;
delete p;
}
else
{
f->Rson=p->Rson;
delete p;
}
}
//以下是p有两个儿子情况的处理
//p有两个儿子,找p的中序前驱
else
{
s=p->Lson; //s是p的左儿子
if(s->Rson==NULL) //s没有右儿子,用s代替p
{
p->data=s->data; //用s的值域代换p的值域
p->Lson=s->Lson; //删去s
delete s;
}
//以下是s有右儿子的情况
else
//s有右儿子,找p的左儿子的最右子孙r
{ r=s->Rson;
while(r->Rson!=NULL)
{
s=r;
r=r->Rson;
}
p->data=r->data; //用r的值域代换p的值域
s->Rson=r->Lson; //删去r
delete r;
}
}
return SUCC; //返回删除成功信息
}
二叉检索树的源代码: // Bitree.cpp : 定义控制台应用程序的入口点。 // // ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<stdio.h> #include<stdlib.h> #include<malloc.h> #define MAXSIZE 100 #define NULL 0 typedef int keytype; typedef int elemtype; typedef struct node { keytype key; //关键字域 elemtype other; //其他数据域 struct node *lchild, *rchild; //左右子树 }bilist; //二叉检索树的节点结构 bilist * insert(bilist *t, bilist*s) /* 将*s结点插入到一棵二叉检索树*r中*/ { bilist *f=NULL; //双亲结点的指针 bilist *p=NULL; //临时指针 p = t; while (p != NULL) { f = p; if (s->key == p->key) //该数值已存在 return t; //若该数值小于根结点,遍历左子树,否则遍历右子树 if (s->key<p->key) p = p->lchild; else p = p->rchild; } //建树失败 if (t == NULL) return s; //若该数值小于双亲结点,作为左孩子,否则作为右孩子 if (s->key<f->key) f->lchild = s; else f->rchild = s; return t; } bilist *creat(keytype r[], int n) //二叉检索树的构造函数算法 { int i; bilist *s, *t; t = NULL; for (i = 0; i<n; i++) { s = (bilist *)malloc(sizeof(bilist)); //动态分配字节为bilist的内存空间 s->key = r[i]; //把数组的元素存入新结点 s->other = NULL; s->lchild = NULL; s->rchild = NULL; //insert(&t,s); t = insert(t, s); } return t; } /* int search(bilist *t,keytype k) //二叉检索树算法 递归算法 { if((t==NULL) || (t->key==k)) return t; else if(t->key<k) return(search(t->rchild,k)); else return(search(t->lchild,k)); } */ int search(bilist *t, keytype k) /*二叉检索树检索算法*/ { while (t != NULL) { //寻找到了,返回该数值 if (t->key == k) return t->key; //若根结点大于查询数,遍历左子树,否则遍历右子树 if (t->key>k) t = t->lchild; else t = t->rchild; } return -1; } //中序输出整棵二叉树 void Show(bilist *t) { if(t!=NULL) { Show(t->lchild); printf("%d ",t->key); Show(t->rchild); } }; int main() { keytype A[MAXSIZE]; int i, data, n = 11; bilist *root; //实例化一个对象 for (i = 0; i<n; i++) { scanf("%d", &A[i]); } printf("\n"); root = creat(A, n); Show(root); //查询某数值 printf("\nplease input the search key:"); scanf("%d", &data); if (search(root, data) != NULL) printf("search succed!\n"); else printf("search failed!\n"); getchar(); system("pause"); }