1、二叉搜索树
---性质:每个结点的关键字,都大于其左子树中所有结点的关键字,而小于其右子树所有结点的关键字。
(若中序遍历一棵二叉搜索树,将得到一个以关键字值递增排列的有序序列)
---搜索:
比较待搜索元素关键字x与根结点关键字;若x较小,进入左子树搜索;若x较大进入右子树搜索。
BTNode<T> *p=root;
while (p)
if ( x<p->element) p=p->lChild;
else if(x>p->element) p=p->rChild;
else return Success;
return NotPresent;
---插入:
根据二叉搜索树的排序性质,通过搜索找插入位置。若搜索成功,则不插入;若搜索失败,则新结点作为树叶插入。
BTNode<T> *p=root,*q=NULL;
//搜索
while (p && p->element!=x){
q=p;
if (x<p->element) p=p->lChild;
else p=p->rChild;
}
//搜索失败则插入
if(p==NULL){
p=new BTNode<T>(x);
if(root==NULL)
root=p; //往空二叉树中插入第一个结点
else
if(x<q->element)
q->lChild=p; //作为左孩子插入
else q->rChild=p; //作为右孩子插入
}
---删除:
a.若被删结点p没有孩子
(用空子树NULL代替p)
b.若被删结点p只有一个孩子
(用p点的唯一孩子c代替p)
c.若被删结点有两个孩子
(找到中序遍历次序下p的直接后继s,将s结点的值复制到p结点中,删除最多只有一棵非空子树的s结点)
BTNode<T> *c,*s,*r,*p=root,*q=NULL;
//搜索
while (p && p->element!=x){
q=p; //q、p 保持父子关系
if(x<p->element) p=p->lChild;
else p=p->rChild;
}
if(!p) return NotPresent;
if (p->lChild && p->rChild){
//找到中序遍历次序下p结点的直接后继s
r=p; s=p->rChild;
while (s->lChild){
r=s; s=s->lChild; // r、s保持父子关系
}
//s结点的值复制到p结点中
p->element=s->element;
//准备删除s结点
q=r; p=s;//现在的p结点就是原来的s结点
}
//待删除的p结点最多只有一个孩子,q指向p的父结点
//准备用p的孩子c(c可能为空)代替p
if (p->lChild) //此时p只有一棵非空的左子树
c=p->lChild; //c指向p的左孩子
else //此时p左子树为空、右子树可能为空
c=p->rChild; //c指向p的右孩子,或为空
//用c代替p
if(p==root) root=c; //删除的是根结点
else //检查被删结点是其双亲的左孩子还是右孩子
if (p==q->lChild)
q->lChild=c ; //删除的是左孩子
else q->rChild=c; //删除的是右孩子
delete p;
return Success;
二叉搜索树的性能分析:
-二叉搜索树的性能取决于二叉搜索树的高度
-n个结点的二叉搜索树,最大高度为n,最小高度为log2n
-将n个结点按关键字从小到大(或从大到小)的次序插入到二叉搜索树,那么得到最大高度的二叉搜索树
-将n个结点按关键字从小到大排列,用二分法搜索每个关键字,按关键字比较次数从小到大的次序将这些结点插入到二叉搜索树,将得到最小高度的二叉搜索树。
-一般情况下,其平均搜索长度为O(lnn)
结论:对于一般的二叉搜索树,其平均搜索长度为O(lnn),和O(log2n)是同一数量级