在前面分享完循序表的查找算法后,今天我们来看看树表中的二叉排序树的相关操作吧
1.二叉排序树的查找操作
二叉排序树的查找算法核心思路:
实现代码:
该算法分析
二叉排序树的平均查找长度的分析:
2.二叉排序树的插入操作 :
算法实现:
void InsertBST(BSTree &T,ElemType e){
if(!T){
S=new BSTNode;
S->data=e;
s->lchild=S->rchild=NULL;
T=S;
}
else if(e.key<T->data.key) InsertBST(T->lchild,e);
else if(e.key>T->data.key) InsertBST(T->rchild,e);
}
3.二叉树的生成操作:
注意:不同插入次序的序列生成不同形态的二叉排序树
算法实现:
void CreatBST(BSTree &T){
T=NULL;
cin>>e;
while(e.key!=ENDFLAG){ //ENDFLAG为自定义的输入结束标志
InsertBST(T,e); //将此结点插入二叉排序树中
cin>>e;
}
}
4.二叉排序树的删除操作:
这种情况比较麻烦,如图要删掉50这个结点,要利用该50结点的中序遍历前驱节点(如图的40结点)去替代它。
结果如图所示:
另一种解法:用如图的80结点(可以理解为右子树最小值结点)替代50结点,
具体算法实现:
int Delete(BiTree *p)
{
BiTree q, s;
//情况 1,结点 p 本身为叶子结点,直接删除即可
if (!(*p)->lchild && !(*p)->rchild)
{
*p = NULL;
}
//左子树为空,只需用结点 p 的右子树根结点代替结点 p 即可;
else if (!(*p)->lchild)
{
q = *p;
*p = (*p)->rchild;
free(q);
q = NULL;
}
//右子树为空,只需用结点 p 的左子树根结点代替结点 p 即可;
else if (!(*p)->rchild)
{
q = *p;
//这里不是指针 *p 指向左子树,而是将左子树存储的结点的地址赋值给指针变量 p
*p = (*p)->lchild;
free(q);
q = NULL;
}
//左右子树均不为空,采用第 2 种方式
else
{
q = *p;
s = (*p)->lchild;
//遍历,找到结点 p 的直接前驱
while (s->rchild)
{
//指向p节点左子树最右边节点的前一个。保留下来
q = s;
s = s->rchild;
}
//直接改变结点 p 的值
(*p)->data = s->data;
//判断结点 p 的左子树 s 是否有右子树,分为两种情况讨论 如果有右子树,s一定会指向右子树的叶子节点。q 此时指向的是叶子节点的父节点。 q != *p二者不等说明有右子树
if (q != *p)
{
//若有,则在删除直接前驱结点的同时,令前驱的左孩子结点改为 q 指向结点的孩子结点
q->rchild = s->lchild;
}
else
//q == *p ==NULL 说明没有右子树
{
//否则,直接将左子树上移即可
q->lchild = s->lchild;
}
free(s);
s = NULL;
}
return TRUE;
}
int DeleteBST(BiTree *T, int key)
{
if (!(*T))
{ //不存在关键字等于key的数据元素
return FALSE;
}
else
{
if (key == (*T)->data)
{
Delete(T);
return TRUE;
}
else if (key < (*T)->data)
{
//使用递归的方式
return DeleteBST(&(*T)->lchild, key);
}
else
{
return DeleteBST(&(*T)->rchild, key);
}
}
}
好啦,关于二叉排序树的内容就分享到这啦
本贴为博主亲手整理。如有错误,请评论区指出,一起进步。谢谢大家的浏览.