二叉搜索树
二叉搜索树的概念
二叉搜索树(二叉排序树 二叉查找树)
根结点值大于其左子树中的所有结点值
根结点值小于其右子树中的所有结点值
左右子树都是二叉搜索树(递归)
typedef struct{
KeyType key; … ;
} ElemType;
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode, *BiTree;
typedef BiTree BSTree;
typedef BiTNode BSTNode;
二叉搜索树的查找
递归
如果树为空,查找失败,返回NULL
否则,从根节点开始,将x与根节点比较
若x小于根节点,递归查找左子树,并返回查找结果
若x大于根节点,递归查找右子树,并返回查找结果
若x等于根节点,查找成功,返回根节点地址
BSTree BSTSearch( BSTree T, KeyType key) {
if( !T) return NULL; //查找失败
else{
if( key > T->data.key )//右子树中递归查找并返回结果
return BSTSearch( T->rChild, key);
else if( key < T->data.key)//左子树递归查找并返回结果
return BSTSearch( T->lchild, key);
else // 查找成功
return T;
}
}
非递归
p最初指向根结点,只要p不空且p所指结点不是所求则:根据比较结果令p变为当前结点的左孩子或右孩子。如此重复至p空或者找到
BiTNode *BSTSearch(BSTree T, KeyType key){
BiTNode *p=T;
while(p && !EQ(key,p->data.key)){
if(LT(key,p->data.key))
p=p->lchild; //向左子树中移动,继续查找
else
p=p->rchild;//向右子树中移动,继续查找
}
if(!p)return NULL;
else return p;//查找结束
}
查找最小和最大元素
二叉检索树的插入
原理
先查找是否有重复节点,无重复则插入,插入位置是最后所走节点的孩子
代码实现
查找过程中同时记录所走节点和其父节点f, 无重复时新开辟节点放到f孩子上
递归关系:与根节点比较,相等则不插入,否则,转换为左或右子树中的插入
递归边界:发现重复不递归,返回ERROR;到达空树不递归,直接开辟节点
注意:空树时插入如何判断?
Status BSTInsert (BSTree &T, ElemType e){ //注意T需要为引用型参数
BSTNode *p=T, *f=NULL;
while(p!=NULL && !EQ(e.key,p->data.key)){
if(LT(e.key, p->data.key)){ f=p; p=p->lchild; }
else{ f=p; p=p->rchild; }
}
if(!p){
q=new BiTNode;
q->data = e; q->lchild = NULL; q->rchild = NULL;
if(!f)T=q;
elise if (e < f->data) f->lchild=q;
else f->richild = q;
return OK;
}
else return ERROR;
}
}
二叉搜索树的创建【补充】
原理
从空树开始,逐个读取节点并插入,直至读到结束符。
代码实现
Status CreateBST(BSTree &T){
T = NULL;
while( InputElem(e)<= 0){
if( BSTInsert (T,e) == ERROR )
return ERROR;
else
InputElem(e);
}
}
删除节点过程
原理:
1.删除叶子节点:直接删除
2.删除只有一个子树的节点:直接将子树接到被删除节点的双亲指针上
3.删除有两个子树节点:将左子树最大或右子树最小移至删除位置,归结为删除左子树最大或者右子树最小节点,这两类节点至多只有一个孩子!
代码实现
1.定位被删除节点及其双亲节点,以便修改双亲节点的指针取值 找不到被删除节点则无需删除,直接返回
p=T;
f=NULL;
while(p!=NULL&&!EQ(key,p->data.key)){
if(LT(key,p->data.key)){
f=p;
p=p->lchild;
}
else{
f=p; p=p->rchild;
}
}
if(!p) return;
2.删除叶节点:释放节点,双亲指针赋空 双亲为空时,除释放节点外,因删除后为空树,T也需赋空
if( !p->lchild&&!p->rchild ){
if(!f){
free(p); p=NULL;
T=NULL;
}else if(f->lchild==p){
free(p); p=NULL;
f->lchild=NULL;
} else {
free(p); p=NULL;
f->rchild=NULL;
}
}
3.删除单子节点:释放节点,双亲指针指向其唯一的孩子 双亲为空时,除释放节点外,T也需修改 此代码同样可以用来删除叶子节点!
if(!p->lchild){//只有右子树(左子树为空)的情况
if(!f) {
T=p->rchild;
free(p); p=NULL;
}else if(f->lchild==p){
f->lchild = p->rchild;
free(p); p=NULL;
}else {
f->rchild = p->rchild;
free(p);p=NULL;
}
}
……//只有左子树时,类似处理
4.汇总
void DeleteBST(BiTree &T,KeyType key){
//首先定位被删结点及其双亲, 不存在则直接返回
p=T; f=NULL;
while(p!=NULL&&!EQ(key,p->data.key)){
if(LT(key,p->data.key)){f=p;p=p->lchild;}else{f=p; p=p->rchild;}
}
if(!p) return;
if(p->lchild&&p->rchild){//若被删节点有两个孩子
f=p; q=p->lchild; //f始终指向q的双亲,方便后面的删除
while(q->rchild){f=q; q=q->rchild;} //q定位最大,f指向其双亲
p->data=q->data; //左子树最大者的值填充到原本被删节点
if(f->lchild==q) f->lchild = q->lchild; else f->rchild=q->lchild;
free(q);
}
else if(!p->lchild){//若左孩子为空(包括只有右孩子或两个孩子都没有的情况)
if(!f) {free(p); T=p->rchild;}
else if(f->rchild==p){f->rchild=p->rchild; free(p);}
else {f->lchild=p->rchild; free(p);}
}
else {…} //只有左孩子,仿照上一段代码, 绿色部分换成p->lchild
} //教材算法9.8没用f和p,而是通过引用传递让p直接表示双亲指针,代码简化
总结与推广
什么样的二叉搜索树查找性能最高?
平衡二叉树 AVL树
概念
任意节点的平衡因子(左右子树深度之差)的绝对值不超过1。
平衡二叉搜索树的构造
先按照二叉搜索树的节点插入方法插入节点,不满足平衡要求时调整!
找到最小不平衡二叉树的根后,根据不平衡种类作相应的旋转!既要保证平衡,也要保证是二叉搜索树!
A这边边比较长
例子
第一个有问题的结点选三个,中间大的往上抬。
断开的左边往左边走,右边往右边走。
插入
删除
B-树(B-Tree)
概念
“平衡”的“多路”“查找”树( 平衡二叉树的推广) 特点:平衡(叶子节点/失败节点同层) ,多关键字,查找树
一颗m阶的B树是空树,或是满足下列特性的m叉树:
n为关键字个数
树上有序,结点也有序。
B-树的查找
从根结点出发,沿树形结构搜索结点和在结点内进行顺序(或折半)查找 两个过程交叉进行。
B-树的查找性能分析
B-树的查找时间主要花在树结点的定位上,这取决于B-树的深度。
B-树的插入(创建)
若查找成功则不能插入,否则,应试图插入到查找路径中最后一个内部结点上。内部结点关键字个数须在Ceil(m/2)-1和m-1之间,若超界则“分裂” 分裂:选中间关键字上移,当前结点分成两个,下层相应分;若上移导致双亲关键字个数超界则继续上移.
B-树的删除
被删节点为最下层非叶节点则直接删,否则用右侧子树最小记录顶替(规约) 内部节点关键字数量有下界Ceil(m/2)-1,低于此值要“求助”或“合并”
B+树(plus)
概念: “平衡”的“多路”“索引”树
特点:平衡(叶子节点/记录节点同层), 多关键字, 索引树, 顺序与随机查找并行
总结与推广
补充:索引顺序表的查找(分块查找)
概念
对数据进行分块,使得块内无序、块间有序。将各块中的最大关键字构成一个索引表,表中还要包含每块的起始地址。
补充:分块查找过程
① 对索引表用折半查找定位最后一个小于等于key的块
② 确定了待查关键字所在的块后,块内采用顺序查找
补充:分块查找性能分析
分块查找优缺点
总结
二叉树
二叉排序树
平衡二叉树
红黑树(不大量做旋转)
B-树(树的深度变大的情况)
逐渐提高查找速率
二叉树可视网站
https://www.cs.usfca.edu/~galles/visualization/BTree.html