【说明】文章内容来源于课程课件
1.定义:二叉排序树或者是一棵空树;或者是具有如下特性的二叉树:
(1)若它的左子树不空,则左子树上所有结点的值均小于根结点的值;
(2)若它的右子树不空,则右子树上所有结点的值均大于根结点的值;
(3)它的左、右子树也都分别是二叉排序树。
说明:二叉排序树的中序遍历序列是排序好的
2.二叉排序树的查找算法:
若二叉排序树为空,则查找不成功;否则
•1)若给定值等于根结点的关键字,则查找成功;
•2)若给定值小于根结点的关键字,则继续在左子树上进行查找;
•3)若给定值大于根结点的关键字,则继续在右子树上进行查找。
两种查找要求:
1. 查找成功,返回结点指针;查找不成功,返回空指针;
2. 查找成功,返回结点指针;查找不成功,返回查找路径上访问的最后一个结点的指针;(第2种算法可用于插入算法)‘
第1种算法:递归实现伪代码:
BiTree SearchBST ( BiTree T, KeyType key)
{ // 返回结点指针或空指针
if ( ! T || EQ(key, T->data.key)
return T; // 查找成功或为空
else if (LT(key, T->data.key) )
return SearchBST ( T->lchild, key );
// 在左子树中继续查找
else return SearchBST ( T->rchild, key );
// 在右子树中继续查找
} // SearchBST
第2种算法:
若查找成功,则返回指向该数据元素的结点的指针 p ,并返回函数值为 TRUE;
否查找不成功,则返回指向查找路径上访问的最后一个结点的指针 p ,并返回函数值FALSE,
为此,定义一个指针 f 指向当前访问的结点的双亲,其初始调用值为NULL
Status SearchBST (BiTree T, KeyType key, BiTree f, BiTree &p ) {
//p是返回指针,f是T的双亲
if (!T) { p = f; return FALSE; } // 查找不成功
else if ( EQ(key, T->data.key) ) { p = T; return TRUE; }// 查找成功
else if ( LT(key, T->data.key) )
SearchBST (T->lchild, key, T, p ); // 在左子树中继续查找
else
SearchBST (T->rchild, key, T, p ); // 在右子树中继续查找
} // SearchBST
3.插入算法
•根据动态查找表的定义,“插入”操作在查找不成功时才进行;
•若二叉排序树为空树,则新插入的结点为新的根结点;否则,新插入的结点必为一个新的叶子结点,其插入位置由查找过程得到。
伪代码:
Status Insert BST(BiTree &T, ElemType e )
{
// 当二叉排序树中不存在关键字等于 e.key 的
// 数据元素时,插入元素值为 e 的结点,并返
// 回 TRUE; 否则,不进行插入并返回FALSE
if (!SearchBST ( T, e.key, NULL, p ))
{ //p为查找路径上访问的最后结点指针
s = new BiTNode;// 为新结点分配空间
s->data = e;
s->lchild = s->rchild = NULL;
if ( !p ) T = s; // 插入 s 为新的根结点
else if ( LT(e.key, p->data.key) )
p->lchild = s; //插入 *s 为*p 的左孩子
else p->rchild = s; //插入 *s 为*p 的右孩子
return TRUE; // 插入成功
}
else return FALSE; //不进行插入并返回FALSE
} // Insert BST
4.删除算法
与插入相反,删除在查找成功之后进行,并且要求在删除二叉排序树上某个结点之后,仍然保持二叉排序树的特性。
可分三种情况讨论:
(1)被删除的结点是叶子:其双亲结点中相应指针域的值改为“空”
(2)被删除的结点只有左子树,或者只有右树:其双亲结点的相应指针域的值改为 “指向被删除结点的左子树或右子树”。
(3)被删除的结点既有左子树,也有右子树:以其前驱替代之,然后再删除该前驱结点
其中删除操作过程如下所描述:
void Delete ( BiTree &p ){
// 从二叉排序树中删除结点 p,
// 并重接它的左子树或右子树
if (!p->rchild) {
//右子树空则只需重接它的左子树
q = p;
p = p->lchild;
delete(q);
}
else if (!p->lchild) {
//左子树为空树则只需重接它的右子树
q = p;
p = p->rchild;
delete(q);
}
else {
// 左右子树均不空,以其前驱替代之,然后再删除该前驱结点
q = p; s = p->lchild;
while (s->rchild) { q = s; s = s->rchild; }// s 指向被删结点的前驱,q是s的双亲
p->data = s->data; //用s 替代被删除结点p
if (q!=p) q->rchild = s->lchild; //修改s双亲指针
else p->lchild = s->lchild;// p的前驱就是其左孩子,// 重接*p的左子树
delete(s);
}
} // Delete
5.查找性能的分析
为了提高查找的效率,也就是减小这个平均查找长度,需要进一步关于二叉平衡树的内容,之后更新~
欢迎批评指正~