全知识整理目录
数据结构整理的目录包括了许多的数据结构相关知识。
目录
概述
什么是平衡二叉搜索树?
首先需要了解一下什么是二叉搜索树?
左子树都小于根节点,右子树都大于根节点,这样的树就是二叉搜索树。
平衡二叉搜索树就是,不仅要是二叉搜索树,还要是平衡的。每个节点都有一个平衡因子,平衡因子为-1,0,1(平衡因子 = 右子树的高度-左子树的高度)的就是平衡二叉搜索树。
要学习的其实就是,插入和删除的时候,二叉树的平衡因子会变化,那么这就是需要学习和了解的难点重点了。
旋转的介绍
左单旋转
如下图所示,在当前平衡的结点上加上一个5,那么3的平衡因子此时就为2,造成不平衡,所以需要,左旋转(逆时针旋转)。
右单旋转
右单旋转,与做单旋转相反,是指新插入的结点位于,左侧子树,且平衡因子不满足。
下图以原本平衡的树,再插入一个2结点,那么就会有右单旋转,恰好跟左单旋转相反,左右旋转是指结点移动的方向。
左右双旋
如下图如果想要插入37,就会导致平衡因子不符合要求,所以需要做出调整。
是怎么样调整的呢?
动图的调整方式可能比较快,可以看见红色的两条分支是需要调整的,而下面的一条就是左旋,上面的一条就是右旋。后面也有详细分解步骤。
第一次左旋,之后发现平衡因子还是不满足。继续右旋。
第二次右旋
有左右双旋,肯定也有右左双旋,右左双旋就不介绍了,本质上跟左右双旋是一样的。
无论怎么旋,只要记得,从下往上,第一个不满足平衡因子的地方开始旋转,往上继续看,还有多少个不满足的平衡因子就旋转多少次,这样就能够解决了。
代码逻辑
首先需要了解树结点的定义
typedef int ElemType;
typedef struct BSTNode
{
ElemType key;
int bf;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
结点的创建
typedef enum
{
EH = 0,
LH = 1,
RH = -1
}bh_t;
typedef enum
{
FALSE = 0,
TRUE = 1
}bool_t;
要实现旋转操作,肯定需要平衡因子发生变化,这里就需要了解插入结点到树中的代码。
插入代码的大概逻辑是:
- 树如果为空的话,直接插入什么也不用考虑。
- 树不为空,判断是大于根节点还是小于根节点,从而找到插入到左边还是右边。
- 然后结点小于父节点的值,就插入到左边,否则插入到右边,相同的数字不予插入。
- 再调整平衡因子,平衡因子的调整会根据父节点进行调整,首先插入结点在子树的父节点++,在子节点--,然后再判断父节点的平衡因子(bf),再根据左旋,右旋,左右旋的函数进行调整。
bool_t InsertAVL(BSTree *t,ElemType e,bool_t *taller)
{
if(NULL == t) //树为空的情况
return FALSE;
if(NULL == *t)
{
*t=(BSTree)malloc(sizeof(BSTNode));
if(NULL == *t)
return FALSE;
(*t)->key=e;
(*t)->lchild=(*t)->rchild=NULL;
(*t)->bf=EH;
*taller=TRUE;
}
else
{
if(e==(*t)->key)
{
*taller=FALSE;
return FALSE;
}
if(e<(*t)->key)
{
if(FALSE == InsertAVL(&((*t)->lchild),e,taller))
return FALSE;
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(FALSE == InsertAVL(&((*t)->rchild),e,taller))
return FALSE;
if(*taller)
{
switch((*t)->bf)
{
case RH:
RightBalance(t);
*taller=FALSE;
break;
case EH:
(*t)->bf=RH;
*taller=TRUE;
break;
case LH:
(*t)->bf=EH;
*taller=FALSE;
break;
}
}
}
}
return TRUE;
}
左单旋
void L_Rotate(BSTree *p)
{
BSTree rc=(*p)->rchild;
(*p)->rchild=rc->lchild;
rc->lchild=*p;
*p=rc;
}
右单旋
void R_Rotate(BSTree *p)
{
BSTree lc=(*p)->lchild;
(*p)->lchild=lc->rchild;
lc->rchild=*p;
*p=lc;
}
完整代码
#include <stdio.h>
#include <malloc.h>
typedef enum
{
EH = 0,
LH = 1,
RH = -1
}bh_t;
typedef enum
{
FALSE = 0,
TRUE = 1
}bool_t;
typedef int ElemType;
typedef struct BSTNode
{
ElemType key;
int bf;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
void InOrderTraverse(BSTree root)
{
if(NULL != root)
{
InOrderTraverse(root->lchild);
printf("%d\t",root->key);
InOrderTraverse(root->rchild);
}
}
void PreOrderTraverse(BSTree root)
{
if(NULL != root)
{
printf("%d\t",root->key);
PreOrderTraverse(root->lchild);
PreOrderTraverse(root->rchild);
}
}
void R_Rotate(BSTree *p)
{
BSTree lc=(*p)->lchild;
(*p)->lchild=lc->rchild;
lc->rchild=*p;
*p=lc;
}
void L_Rotate(BSTree *p)
{
BSTree rc=(*p)->rchild;
(*p)->rchild=rc->lchild;
rc->lchild=*p;
*p=rc;
}
void LeftBalance(BSTree *T)
{
BSTree lc=(*T)->lchild;
BSTree rd = lc->rchild;
switch(lc->bf)
{
case LH:
(*T)->bf=lc->bf=EH;
R_Rotate(T);
break;
case RH:
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=LH;
break;
}
rd->bf=EH;
L_Rotate(&((*T)->lchild));
R_Rotate(T);
break;
}
}
void RightBalance(BSTree *T)
{
BSTree rc=(*T)->rchild;
BSTree ld=rc->lchild;
switch(rc->bf)
{
case RH:
(*T)->bf=rc->bf=EH;
L_Rotate(T);
break;
case LH:
switch(ld->bf)
{
case RH:
(*T)->bf=LH;
rc->bf=EH;
break;
case EH:
(*T)->bf=rc->bf=EH;
break;
case LH:
(*T)->bf=EH;
rc->bf=RH;
break;
}
ld->bf=EH;
R_Rotate(&((*T)->rchild));
L_Rotate(T);
break;
}
}
bool_t InsertAVL(BSTree *t,ElemType e,bool_t *taller)
{
if(NULL == t)
return FALSE;
if(NULL == *t)
{
*t=(BSTree)malloc(sizeof(BSTNode));
if(NULL == *t)
return FALSE;
(*t)->key=e;
(*t)->lchild=(*t)->rchild=NULL;
(*t)->bf=EH;
*taller=TRUE;
}
else
{
if(e==(*t)->key)
{
*taller=FALSE;
return FALSE;
}
if(e<(*t)->key)
{
if(FALSE == InsertAVL(&((*t)->lchild),e,taller))
return FALSE;
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(FALSE == InsertAVL(&((*t)->rchild),e,taller))
return FALSE;
if(*taller)
{
switch((*t)->bf)
{
case RH:
RightBalance(t);
*taller=FALSE;
break;
case EH:
(*t)->bf=RH;
*taller=TRUE;
break;
case LH:
(*t)->bf=EH;
*taller=FALSE;
break;
}
}
}
}
return TRUE;
}
BSTree searchAVL(BSTree t,ElemType key)
{
BSTree p=t;
while(p)
{
if(p->key==key)
return p;
else if(p->key<key)
p=p->rchild;
else
p=p->lchild;
}
return p;
}
static void destroy(BSTree *t)
{
if(NULL != *t)
{
destroy(&((*t)->lchild));
destroy(&((*t)->rchild));
free(*t);
*t = NULL;
}
return;
}
void destroyAVL(BSTree root)
{
if(NULL != root)
{
destroy(&root);
}
return;
}
int main(int argc,char *argv[])
{
BSTree root=NULL,r;
bool_t taller=FALSE;
int array[]={13,24,37,90,53};
int i = 0;
for(i=0;i<5;i++)
InsertAVL(&root,array[i],&taller);
printf("inorder traverse\n");
InOrderTraverse(root);
printf("\npreorder traverse\n");
PreOrderTraverse(root);
printf("\nsearch key\n");
r=searchAVL(root,37);
if(r)
{
printf("%d\n",r->key);
}
else
{
printf("not find!\n");
}
destroyAVL(root);
root = NULL;
}