二叉排序树的基本概念和查找
定义:二叉排序树或者是一棵空树;或者是具有如下特性的二叉树:
①若它的左子树不空,则左子树上所有结点的值均小于根结点的值;
②若它的右子树不空,则右子树上所有结点的值均大于根结点的值;
③它的左、右子树也都分别是二叉排序树。
二叉排序树的定义是一个递归定义的过程。
保证小于根结点值的结点都落在左子树上,而大于根结点值的结点都落在右子树上。
查找步骤:
①若给定值等于根结点的关键字,则查找成功;
②若给定值小于根结点的关键字,则继续在左子树上进行查找;
③若给定值大于根结点的关键字,则继续在右子树上进行查找。
在二叉排序树上进行查找,类似折半查找。
查找算法
//递归实现
BSTree SearchBST(BSTree bst, KeyType key){
if(!bst) return NULL;
else if(bst->key==key) return bst;
else if(key<bst->key)
return SearchBST(bst->lchild,key);
else
return SearchBST(bst->rchild,key);
}
二叉排序树的插入与删除
“插入”操作在查找不成功时才进行;
若二叉排序树为空树,则新插入的结点为新的根结点。
二叉排序树插入算法:
void InsertBST(BSTree *bst, KeyType key){//key待插关键字
BiTree s;
if(*bst==NULL){
s=(BSTree)malloc(sizeof(BSTNode));
s->key=key;
s->lchild=NULL;
s->rchild=NULL;
*bst=s;
}
else if(key<(*bst)->key)//左子树上继续查找
InsertBST(&((*bst)->lchild),key);
else if(key>(*bst)->key)//右子树上查找
InsertBST(&((*bst)->rchild),key);
}
二叉排序树生成算法:
二叉排序树的形态完全由关键字的输入顺序决定。
例如:设关键字输入顺序为:45,24,53,12,28,90
从空树开始,第一个关键字作为根结点开始往下遍历,比结点小的插到左支,大的插到右支。
void CreateBST(BSTree *bst){
KeyType key;
*bst=NULL;
scanf("%d",&key);
while(key!=ENDKEY){
InsertBST(bst,key);
scanf("%d",&key);
}
}
二叉排序树的特点:
- 中序遍历二叉排序树可得到关键字有序序列。
- 在构造二叉排序树时,每次插入的新结点都是新的叶子结点,所以进行插入时不必移动其它结点。
- 二叉排序树不但拥有类似于折半查找的特性,又采用了链表作存储结构,因此是动态查找表的一种适宜表示。
二叉排序树的删除
和插入相反,删除在查找成功之后进行,并且要求在删除二叉排序树上某个结点之后,仍然保持二叉排序树的特性。
(1)被删除的结点是叶子结点;
(2)被删除的结点只有左子树或只有右子树
如果被删除的结点有子树,删除之后,将其子树挂到双亲结点对应的分支上,其双亲结点的相应指针域的值改为“指向被删除结点的左子树或右子树”;
(3)被删除的结点既有左子树又有右子树
二叉排序树中序遍历结果:
20 30 32 35 40 50 88 85 90 80
用其前驱或后继替代之,然后再删除该前驱或后继结点,即用左子树最右边的结点或右子树最左边的结点来代替,此例中可以用40或88代替,
二叉排序树插入算法的实现:
BSTNode * DelBST(BSTree t, KeyType k){//t是二叉树的根
BSTNode *p,*f,*s,*q;
p=t;
f=NULL;
while(p){
if(p->key==k) break;
f=p;
if(p->key>k) p=p->lchild;
else p=p->rchild;
}
if(p==NULL) return t;
if(p->lchild==NULL){
if(f=NULL) t=p->rchild;
else if(f->lchild==p) f->lchild=p->rchild;
else f->rchild=p->rchild;
free(p);
}
else{
q=p;
s=p->lchild;
while(s->rchild){
q=s;
s=s->rchild;
}
if(q==p) q->lchild=s->lchild;
else q->rchild=s->lchild;
p->key=s->key;
free(s);
}
return t;
}
二叉排序树性能分析:
例如,由序列3,1,4,2,5构造而得的二叉排序树
ASL succ =(1+2+3+4+5)/5 = 3
ASL succ =(1+2*2+2*3)/5 = 2.2
最差情况退化为单支树与顺序查找相同;
最好情况是与折半查找判定树相同。
- 中序遍历二叉排序树可以得到关键字的有序序列;
- 在构造二叉排序树的时候,不需要移动其他节点;
- 二叉排序树可以得到折半查找一样好的时间性能并且由于它是链式存储,所以二叉排序树的插入和删除相对的元素移动量都是非常少的。