若再许我少年时,一两黄金一两风...|

之于尘

园龄:3年3个月粉丝:1关注:1

2021-11-16 12:22阅读: 1044评论: 0推荐: 0

二叉排序树的查找、插入、删除

一、定义

二叉排序树(BST)(二叉查找树)或者是一棵空树,或者是具有下列特性的二叉树:

1)若左子树非空,则左子树上所有的结点的值均小于根结点的值。

2)若右子树非空,则右子树上所有结点的值均大于根结点的值。

3)左右子树均是一棵二叉排序树

注意:由二叉排序树的定义可知,左子树结点值<根结点值<右子树结点值,所以如果我们对二叉排序树进行中序遍历(左根右),可以得到一个递增(这里的递增是针对于结点值而言,也就是查找的关键字)的有序序列

二叉树排序树的结构体

/*其实就是二叉树的二叉链表的结点定义*/
typedef struct BiTNode
{
ElemType data;//关键字
struct BiTNode *lchild,*rchild;//左右孩子
}BiTNode,*BiTree;

二叉排序树的建立

void CreatBST(BiTree &T,KeyType str[],int n)
{
T=NULL;
int i=0;
while(i<n)
{
InsertBST(T,str[i]);
i++;
}
}

二、二叉排序树的查找

算法描述:从根结点开始,沿着某个分支逐层向下比较。若二叉排序树非空,先将给定值与根结点的关键字比较,若相等,则查找成功;若不等,如果小于根结点的关键字,则在根结点的左子树上查找,否则在根结点的右子树上查找。

1.递归实现

int SearchBST(BiTree T,int key,BiTree f,BiTree &p)//二叉树f指向T的双亲
{
if(T==NULL)
{
p=f;
return 0;
}
else if(key==T->data)//查找成功,则P指向该数据元素结点
{
p=T;
return 1;
}
else if(key<T->data)//在左子树中继续查找
{
return SearchBST(T->lchild,key,T,p);
}
else//在右子树中继续查找
{
return SearchBST(T->rchild,key,T,p);
}
}

2.非递归实现

BiTNode *SearchBST(BiTree T,ElemType key)
{
while(T!=NULL&&key!=T->data)//若树为空或者等于根结点值,则结束循环
{
if(key<T->data)//小于,则在左子树查找
{
T=T->lchild;
}
else//大于,则在右子树查找
{
T=T->rchild;
}
}
return T;
}

三、二叉排序树的插入

算法描述:若二叉排序树为空,则直接插入结点;否则,若关键字key小于根节点值,则插入到左子树,若关键字key大于根结点值,则插入到右子树。

注意:插入的结点一定是一个新添加的叶子结点,且是查找失败时的查找路径上访问的最后一个结点的左孩子或右孩子。

int insertBST(BiTree &T,KeyType key)
{
if(T==NULL)
{
T=(BiTree)malloc(sizeof(BiTNode));
T->data=key;
T->lchild=T->rchild=NULL;
return 1;
}
else if(key==T->data)
{
return 0;
}
else if(key<T->data)
{
return InsertBST(T->lchild,key);
}
else
{
return InsertBST(T->rchild,key);
}
}

四、二叉排序树的删除

算法描述:分三种情况

  • 若被删除结点是叶子结点,则直接删除,不会破坏二叉排序树的性质。
  • 若被删除结点只有左子树或者右子树,则让该结点的子树代替该结点的位置。
  • 若被删除结点有左右两棵子树,则令该结点中序遍历下的直接前驱或直接后继替代该结点,然后从二叉排序树中删去这个直接前驱或直接后继,这样就转换成了第一或第二种情况。

image

/* 从二叉排序树中删除结点p,并重接它的左或右子树。 */
int 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; /* s指向被删结点的直接前驱(将被删结点前驱的值取代被删结点的值) */
if(q!=p)
{
q->rchild=s->lchild; /* 重接q的右子树 */
}
else//说明p==q,也就是说前面的while循环没有进行,也就是说一开始s没有右子树,此时直接将s的左子树接到q的左子树上就行
{
q->lchild=s->lchild; /* 重接q的左子树 */
}
free(s);
}
return 1;
}
/* 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素结点, */
/* 并返回1;否则返回0。 */
int DeleteBST(BiTree T,KeyType key)
{
if(T==NULL) /* 不存在关键字等于key的数据元素 */
{
return 0;
}
else
{
if (key==T->data) /* 找到关键字等于key的数据元素 */
{
return Delete(T);
}
else if (key<T->data)
{
return DeleteBST(T->lchild,key);//左子树
}
else
{
return DeleteBST(T->rchild,key);//右子树
}
}
}

本文作者:之于尘

本文链接:https://www.cnblogs.com/cdjlx/p/15560567.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   之于尘  阅读(1044)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起