二叉排序树:( BST : Binary_Sort_Tree )
设查找的数据集是普通的顺序存储,那么插入操作就是将记录放在表的末端,给表记录数加一即可,删除操作可以删除后,后面的记录向前移,也可以是要删除的元素与最后一个元素互换,表记录数减一,反正整个数据集也没有什么顺序,这样的效率也不错。应该说,插入和删除对于顺序存储结构来说,效率是可以接受的,但是这样的表由于无序造成查找的效率很低 如果查找的数据集是有序线性表,并且是顺序存储的,查找可以用折半、插值、斐波那契等查找算法来实现,可惜因为有序,在插入和删除操作上,就需要耗费大量的时间。有没有一种即可以使得插入和删除效率不错,又可以比高效率地实现查找的算法呢?
二叉排序树的查找要在一开始就建立一个排序树的存储结构。
/*查找,注意二重指针的巧妙利用*/
typedef struct Binary
{
int data;
struct Binary *lchild,*rchild
}BiTNode,*BiTree;
Status SearchBST(BiTree T,int key,BiTree f,BiTree *p)
{ //p是二重指针
if(!T){
*p = f;
return FALSE;
}else if(key == T->data){
*p = T;
return TRUE;
}else if(key < T->data){ //在左边找咯
return SearchBST(T->lchild,key,T,p);
}else{ //key > T->data,在右边找
return SearchBST(T->rchild,key,T,p);
}
}
/*当不存在这个 key 时,怒插一个在里面(手动滑稽)*/
Status InsertBST(BiTree T,int key)
{
BiTree p,s;
if( !SearchBST(*T, key, NULL, &p) ) //1、
{
s = (BiTree)malloc(sizeof(BiTNode));
s->data = key;
s->lchild = s->rchild = NULL;
if(!p){ //!p说明树不存在。。
*T= s; //插入s为新的根节点
}else if(key < p->data) //p有所指
p->lchild = s;
else //(key > p->data)
p->rchild = s;
return TRUE;
}
else
return FALSE;
}
//1、 因为p是二重指针,所以在内存里保存下来。
//search函数返回false时,if成立,说明要么这是个空树,
//要么因为最终到达树底也没找到该节点。比如你想找 9 这个
//节点,树中有一个叶节点8,那么下一步递归就去寻找8的
//右子树,8哪来的右子树?!自然递归过去的T->xchild为空
//进入if语句后,因为p = *T,若p不存在说明不存在树,
//然后巴拉巴拉~~~
/*创建一个已知节点的树~~~*/
int i;
int a[10] = {62,88,58,47,35,73,51,99,37,93};
BiTree T = NULL;
for(i = 0; i < 10 ; i++ )
{
InsertBST(&T,a[i]); //哈哈
}
/*删除较麻烦,保持二叉排序树不能从中间断掉,所以分类讨论*/
//1、一是删除叶子结点,很容易
//2、而是删除只有左子树或只有右子树的节点,相对也比较好解决,
//只需要将整个左右子树进行移动和删除即可,
Status DeleteBST(BiTree *T,int key) //查找到key后删除
{
if(!*T)
return FALSE;
else{
if(key == (*T)->data)
return Delete(T); //delete在下面
else if(key < (*T)->data))
return DeleteBST(&(*T)->lchild,key) //key比较小,那一定在左边~
else
return DeleteBST(&(*T)->rchild,key)
}
}
Status Delete(BiTree *p)
{
BiTree q,s;
if((*P)->rchild == NULL){ // 包含了所有叶子结点的情况
q = *p; *p = (*p)->lchild; free(q);
}else if((*p)->lchild == NULL){ //说明只有右子树~
q = *p; *p = (*p)->rchild; free(q);
}else{ //左右子树都不空
q = *p; s = (*p)->lchild;
while(s->rchild) //转一下左。再一直向右。看图~
{
q = s; s = s->rchild;
}
(*p)->data = s->data; //37覆盖47
if(q != *p) //1、
q->rchild = s->lchild; //重接 q 的右子树
else
q->lchild = s->lchild; //重接 q 的右子树
free(s);
}
return TRUE;
}
//1、注意!q = *p的情况是:(*p)->lchild 没有左子树~
// ————-《大话数据结构》