前言
在线性表中进行顺序查找在最坏的情况和平均情况下都需要O(n)的时间,二分需要O(logn)的时间但是二分查找的前提是线性表必须是有序的,如果无序则,则二分查找无意义。顺序查找和二分查找适合静态查找。如果在查找过程中有插入、删除等操作,则在最坏情况下和平均情况下都需要O(n)的时间。而将二分查找策略与二叉树结合起来,实现二叉查找结构,就可以达到单次修改和查找均在O(logn)之中完成。
一、二叉查找树(BST)是什么?
它或者是一棵空树,或者是具有下列性质的 二叉树 : 若它的左子树不空,则左子树上所有结点的值均小于它的 根结点 的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为 二叉排序树 。
二、二叉查找树的创建和删除
1.二叉树的插入
代码如下(示例):
void InsertBST(BSTree& T, int data)
{
if (T == NULL)//找到插入位置
{
BSTree S = new TreeNode;
S->data = data;
S->lchild = S->rchild = NULL;
T = S;
return;
}
if (T->data == data) return;//若已存在不做操作
else if (T->data > data)
{
InsertBST(T->lchild, data);//若插入数据小于根节点向左子树递归查找
}
else
{
InsertBST(T->rchild, data);//反则向右子树递归查找
}
}
2.数据删除
数据删除的话分为四种:
1删除的数据节点为叶子节点:
这种情况的话很好操作只要将该节点的双亲节点指向该节点的指针指向NULL,再delete该节点即可。
2删除的数据节点仅含有左子树:
这种情况需要将待删除节点的双亲节点的指向该节点的指针指向待删除节点的左子树即可(有点绕,可以仔细看看)。
3删除的数据节点仅含有右子树:
这种情况需要将待删除节点的双亲节点的指向该节点的指针指向待删除节点的右子树即可(和情况2类似)。
4删除的数据节点同时含有左右子节点:
这种情况的话最为复杂,也有两种方法,我么知道,二叉搜索树的子树也是一颗二叉搜索树,所以要代替该子树的根节点可以用1:左子树的最右节点(左边最大值)或2:右子树的的最左节点(右边的最小值)来代替根节点。这样的话任然保留了二叉搜索树的特性。
取代方法:首先将根节点的值赋给根节点然后在递归删除原节点。
代码:
void DeleteBST(BSTree& T, int data)
{
BSTree p = T;//传入节点
BSTree f = NULL;
BSTree q;
BSTree s;//f永远是p的双亲节点,q,s参与递归寻找替换节点(左右子树都存在情况),q为s的双亲节点。
if (!p) return;// 如果为空则返回。
while (p)
{
if (p->data == data)
break;//找到结束循环
f = p;
if (p->data > data)
p = p->lchild;
else
p = p->rchild;
}
if (!p) return;//如果找不到则返回
if (p->lchild && p->rchild)//这里我们选用取左边最大值的方法
{
q = p;
s = p->lchild;
while (s->rchild)
{
q = s;
s = s->rchild;
}
p->data = s->data;//这里有种特殊情况:p的左子树没有右子树即p的左子树为左子树最大值。
if (q != p)
q->rchild = s->lchild;//一般情况
else
q->lchild = s->lchild;//特殊情况
}
else//另外三种情况
{
if (!p->rchild)//p无右子树
{
q = p;//q存放原来的p下面会判断连接节点在双亲的位置
p = p->lchild;
}
if(!p->lchild)//无右子树
{
q = p;
p = p->rchild;
}
//接下来判断删除的节点位置根节点 或是 其他节点
if (!f)//根节点
{
T = p;
}
else if (f->lchild == q)
{
f->lchild = p;//判断序需连接节点要连在双亲节点的位置
}
else
f->rchild = p;
delete q;
}
}
总结
以上就是今天的关于二叉搜索树的创建,删除以及相关知识,希望对大家有所帮助。