动态查找表:表在查找过程中动态生成。
如果查找成功,返回。失败,就将新的记录插入到表中。
1.二叉排序树 or 二叉查找树 Binary Sort Tree
性质:1.或是空树,或具有以下性质
2.左子树的所有结点值都小于根节点值
3.右子树的所有结点值都大于根节点值
4.它的左右子树也分别为二叉排序树
查找过程:
BiTree SearchBST(BiTree T, KeyType key){
if(!T) return NULL;
if(EQ(key,T->data.key)) rturn T;
else if(LT(key,T->data.key)) return SearchBST(T->lchild,key);
else return SearchBST(T->rchild,key);
}
相对于次优二叉树,二叉排序树是一种动态树表。
查找失败,将新的记录作为树的叶子结点插入,而且是查找失败的最后结点的左子树或者右子树。
修改的查找过程:
Status SearchBST(BiTree T, KeyType key,BiTree f,BiTree *p){
if(!T){p = f; return FALSE;}
if(EQ(key,T->data.key)) {p = T; return TRUE;}
else if(LT(key,T->data.key)) SearchBST(T->lchild,key,f,p);
else SearchBST(T->lchild,key,f,p);
}
Status Insert_BST(BiTree *T,ElemType e){
if(!SearchBST(T,e.key,NULL,p)){
s = (BiTree)malloc(sizeof(BTNode));
if(LT(e.key,p->data.key)) p->lchild = s;
else p->rchild = s;
return TRUE;
}
return FALSE;
}
如此插入,如果按照有序序列插入的话,得到了是一支单枝树。查找效率极差。
正是有这个考虑,所以需要对二叉查找树进行平衡。避免左右子树过大的层次差。
关于二叉排序树上结点的删除:
1.删除的是叶子结点,直接删除
2.非叶子结点:
a。 只有单一子树,只需要重接子树
b。 有两个非空子树,调整如下
Status Delete_BST(BiTree T, KeyType key){
if(!T) return FALSE;
if(EQ(key,T->data.key)) Delete(T);
else if(LT(key,T->data.key)) Delete_BST(T->lchild,key);
else Delete_BST(T->rchild,key);
rturn TRUE;
}
void Delete(BiTree *p){
//如果不同时存在两棵非空子树
if(!p->rchild){
q = p; p = p->lchild; delete(q);
}
else if(!p->lchild){
q = p; p = p->rchild; delete(q);
}
//有两棵非空子树,找到要删除结点的前驱结点s,用s结点替代p结点
else{
//先左转,然后向右到尽头,找到前驱结点s,q指向前驱结点的父节点
q = p ; s = p->lchild;
while(s->rchild) {q = s; s = s->rchild;}
p->data = s->data;
if(q = p) q->lchild = s->lchild; //没有经过while循环,前驱结点为它的左子树,s为q的左子树
else q->rchild = s ->lchild; //经过了while循环,s变为了q的右子树
}
}
2.平衡二叉树 Balance Binary Tree AVL树
平衡二叉树性质:左右子树的深度之差的绝对值不超过1;
平衡因子:BF balance factor 左右子树的深度之差的绝对值,取值为+1,0,-1.
typedef struct BSTNode{
ElemType data;
int bf;
struct BSTNode *lchild, *rchild;
}BSTNode, *BSTree;
//右旋转,在左子树的左子树添加结点,根节点的bf由1-》2
//呈现的是左边的单枝树,需要右向顺时针旋转
void R_Rotate(BSTree *T){
lc = p->lchild;
p->lchild = lc->rchild;
lc->rchild = p;
p = lc;
}
//左旋转,在右子树的右子树添加结点,根节点的bf由-1-》-2
//呈现的是右边的单枝树,需要左向逆旋
void L_Rotate(BSTree *T){
lc = p->rchild;
p->rchild = lc->lchild;
lc->rchild = p;
p = lc;
}
#define LH +1 左高
#define EH 0 等高
#define RH -1 右高
Status InsertAVL(BSTree *T,ElemType e,Boolean *taller){
if(!T){
T = (BSTree)malloc(sizeof(BSTNode));
T->lchild = NULL; T->rchild = NULL;
T->data = e; T->bf = EH; taller = TRUE;
}
else{
if EQ(e.key,T->data.key){
taller = FALSE; return 0;
}
if LT(e.key,T->data.key){
if(!InserAVL(T->lchild,e,taller)) return 0;
if(taller)
switch(T->bf){
case LH:
LeftBalance(T); taller = FALSE; break;
case EH:
T->bf= LH; taller = TRUE; break;
case RH:
T->bf = EH; taller = FALSE; break;
}
}
else{
if(!InserAVL(T->rchild,e,taller)) return 0;
if(taller)
switch(T->bf){
case LH:
T->bf= EH; taller = FALSE; break;
case EH:
T->bf= RH; taller = TRUE; break;
case RH:
RightBalance(T); taller = FALSE; break;
}
}
}
return 1;
}
void LeftBalance(BSTree *T){
lc = T->lchild;
swith(lc->bf){
case LH:
T->bf = lc->bf = EH;
R_Rotate(T); Break;
case RH:
rd = lc->right;
switch(rd->bf){
case LH: T->bf = RH; lc->bf = EH; break;
case EH: T->bf = lc->bf = EH; break;
case RH: T->bf = EH; lc->bf = RH; break;
}
rd ->bf = EH;
L_Rotate(T->lchild);
R_Rotae(T);
}
}
3.B- 树 B+树 键树
平衡的多路查找树。
如果查找成功,返回。失败,就将新的记录插入到表中。
1.二叉排序树 or 二叉查找树 Binary Sort Tree
性质:1.或是空树,或具有以下性质
2.左子树的所有结点值都小于根节点值
3.右子树的所有结点值都大于根节点值
4.它的左右子树也分别为二叉排序树
查找过程:
BiTree SearchBST(BiTree T, KeyType key){
if(!T) return NULL;
if(EQ(key,T->data.key)) rturn T;
else if(LT(key,T->data.key)) return SearchBST(T->lchild,key);
else return SearchBST(T->rchild,key);
}
相对于次优二叉树,二叉排序树是一种动态树表。
查找失败,将新的记录作为树的叶子结点插入,而且是查找失败的最后结点的左子树或者右子树。
修改的查找过程:
Status SearchBST(BiTree T, KeyType key,BiTree f,BiTree *p){
if(!T){p = f; return FALSE;}
if(EQ(key,T->data.key)) {p = T; return TRUE;}
else if(LT(key,T->data.key)) SearchBST(T->lchild,key,f,p);
else SearchBST(T->lchild,key,f,p);
}
Status Insert_BST(BiTree *T,ElemType e){
if(!SearchBST(T,e.key,NULL,p)){
s = (BiTree)malloc(sizeof(BTNode));
if(LT(e.key,p->data.key)) p->lchild = s;
else p->rchild = s;
return TRUE;
}
return FALSE;
}
如此插入,如果按照有序序列插入的话,得到了是一支单枝树。查找效率极差。
正是有这个考虑,所以需要对二叉查找树进行平衡。避免左右子树过大的层次差。
关于二叉排序树上结点的删除:
1.删除的是叶子结点,直接删除
2.非叶子结点:
a。 只有单一子树,只需要重接子树
b。 有两个非空子树,调整如下
Status Delete_BST(BiTree T, KeyType key){
if(!T) return FALSE;
if(EQ(key,T->data.key)) Delete(T);
else if(LT(key,T->data.key)) Delete_BST(T->lchild,key);
else Delete_BST(T->rchild,key);
rturn TRUE;
}
void Delete(BiTree *p){
//如果不同时存在两棵非空子树
if(!p->rchild){
q = p; p = p->lchild; delete(q);
}
else if(!p->lchild){
q = p; p = p->rchild; delete(q);
}
//有两棵非空子树,找到要删除结点的前驱结点s,用s结点替代p结点
else{
//先左转,然后向右到尽头,找到前驱结点s,q指向前驱结点的父节点
q = p ; s = p->lchild;
while(s->rchild) {q = s; s = s->rchild;}
p->data = s->data;
if(q = p) q->lchild = s->lchild; //没有经过while循环,前驱结点为它的左子树,s为q的左子树
else q->rchild = s ->lchild; //经过了while循环,s变为了q的右子树
}
}
2.平衡二叉树 Balance Binary Tree AVL树
平衡二叉树性质:左右子树的深度之差的绝对值不超过1;
平衡因子:BF balance factor 左右子树的深度之差的绝对值,取值为+1,0,-1.
typedef struct BSTNode{
ElemType data;
int bf;
struct BSTNode *lchild, *rchild;
}BSTNode, *BSTree;
//右旋转,在左子树的左子树添加结点,根节点的bf由1-》2
//呈现的是左边的单枝树,需要右向顺时针旋转
void R_Rotate(BSTree *T){
lc = p->lchild;
p->lchild = lc->rchild;
lc->rchild = p;
p = lc;
}
//左旋转,在右子树的右子树添加结点,根节点的bf由-1-》-2
//呈现的是右边的单枝树,需要左向逆旋
void L_Rotate(BSTree *T){
lc = p->rchild;
p->rchild = lc->lchild;
lc->rchild = p;
p = lc;
}
#define LH +1 左高
#define EH 0 等高
#define RH -1 右高
Status InsertAVL(BSTree *T,ElemType e,Boolean *taller){
if(!T){
T = (BSTree)malloc(sizeof(BSTNode));
T->lchild = NULL; T->rchild = NULL;
T->data = e; T->bf = EH; taller = TRUE;
}
else{
if EQ(e.key,T->data.key){
taller = FALSE; return 0;
}
if LT(e.key,T->data.key){
if(!InserAVL(T->lchild,e,taller)) return 0;
if(taller)
switch(T->bf){
case LH:
LeftBalance(T); taller = FALSE; break;
case EH:
T->bf= LH; taller = TRUE; break;
case RH:
T->bf = EH; taller = FALSE; break;
}
}
else{
if(!InserAVL(T->rchild,e,taller)) return 0;
if(taller)
switch(T->bf){
case LH:
T->bf= EH; taller = FALSE; break;
case EH:
T->bf= RH; taller = TRUE; break;
case RH:
RightBalance(T); taller = FALSE; break;
}
}
}
return 1;
}
void LeftBalance(BSTree *T){
lc = T->lchild;
swith(lc->bf){
case LH:
T->bf = lc->bf = EH;
R_Rotate(T); Break;
case RH:
rd = lc->right;
switch(rd->bf){
case LH: T->bf = RH; lc->bf = EH; break;
case EH: T->bf = lc->bf = EH; break;
case RH: T->bf = EH; lc->bf = RH; break;
}
rd ->bf = EH;
L_Rotate(T->lchild);
R_Rotae(T);
}
}
3.B- 树 B+树 键树
平衡的多路查找树。