1二叉查找树
1.1特点
- 任意节点的左子树不空, 则左子树上所有节点的key均小于它的根节点的key
- 任意节点的右子树不空, 则右子树上所有节点的key均大于它的根节点的key
- 任意节点的左,右子树也分别为二叉查找树
- 没有key相等的节点
- 二叉查找树进行中序遍历,可以得到一个递增的有序序列
1.2结构
struct Node {
int key;
struct Node* left;
struct Node* right;
}
1.3操作
1.3.1创建
1.3.2插入
Node* Insert(Node*& node, int key){
if(!search(node,key)){
if(NULL == node) {
node = new Node(key);
}
if (key < node->key){
node->left = Insert(node->left, key);
}else if (key > node->key){
node->right = Insert(node->right,key);
}
return node;
}else{
return NULL:
}
}
1.3.3查找
Node* Search(Node* node, int key){
if(NULL == node) {
return NULL;
}
if (key < node->key){
return Search(node->left, key);
}else if (key > node->key) {
return Search(node->right, key);
}
return node;
}
1.3.4删除
二叉查找树的删除操作是相对复杂一点,它要按 3 种情况来处理:
1:被删除结点是叶子结点,直接删除。
2:结点只有左子树或只有右子树,则让子树替代;
3:结点既有左子树,又有右子树,有两种处理方式
1: 替代删除,后继代替删除节点,然后删除后继;或者前驱代替删除节点,然后删除前驱。
2:合并删除,右子树合并到左子树的最大值的右子树上;或者左子树合并到右子树最小值的左子树上。
Node* DeleteBST(Node** T, int key){
if(!*T){
return false;
}else{
if(key==(*T)->key)){
return Delete(T);
}
else if(key<(*T)->key){
return DeleteBST(&(*T)->left, key);
}
else{
return DeleteBST(&(*T)->right, key);
}
}
}
Node* DeleteBST(Node** p){
Node * q,s;
//
if((*p)->rchild==NULL){
q=*p;
*p=(*p)->lchild;
free(q);
}
else if((*p)->lchild==NULL){
q=*p;
*p=(*p)->rchild;
free(q);
}
else{
q=*p;
s=(*p)->lchlid;
while(s->rchild){
q=s;
s=s->lchlid;
}
//只是把前驱的值放在了删除结点上
(*p)->data=s->data;
//有右子树
if(q!=*p){
q->rchild=s->lchild;
}else{//没有
q->lchild=s->lchlid;
}
free(s);
}
return true;
}
BST树的缺点不平衡所有有下面的AVL树
2.AVL树(平衡二叉树)
2.1概念
平衡二叉树/自平衡二叉查找树(Balanced Binary Tree): 也称为AVL树(名称来自发明人G.M. Adelson-Velsky 和 E.M. Landis的首字母),它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。树快速查找的关键是高度要低,高度低的关键是平衡。
非平衡二叉树
平衡二叉树
2.2平衡因子
平衡因子BF(Balance Factor):左树深度减去右树深度的值。平衡因子BF = 左子树深度-右子树深度。
平衡二叉树每个结点的平衡因子只能是1,0,-1。若其绝对值超过1,则该二叉排序树就是不平衡的。当BF为-1、0、1时,二叉树平衡;反之,不平衡。
两种旋转(左旋/右旋)、三个节点(新插入节点/不平衡节点/旋转节点)、四种不平衡(LL/RR/RL/LR)。
2.3两种旋转
旋转条件:
当最小不平衡子树根节点 BF>1,右旋 ;BF<-1,左旋。
旋转步骤:
- 获取旋转节点
- 旋转节点的子节点替换父节点的旋转节点
- 旋转节点父节点做旋转节点子节点
- 返回旋转节点
2.3.1左旋
void R_Rotate(Tree *p){
Tree L;
L=(*p)->Rchild;
(*p)->rchild=L->lchild;
L->lchild=(*p);
(*p)=L
}
2.3.1右旋
void R_Rotate(Tree *p){
Tree L;
L=(*p)->lchild;
(*p)->lchild=L->rchild;
L->rchild=(*p);
(*p)=L
}
2.4四种不平衡
类别 | 说明 |
---|---|
LL 左左情况 | 插入一个新节点到不平衡节点的左子树(Left)的左子树(Left),导致不平衡节点的平衡因子由1变为 |
RR 右右情况 | 插入一个新节点到不平衡节点的右子树(Right)的右子树(Right),导致不平衡节点的平衡因子由-1变为-2 |
LR 左右情况 | 插入一个新节点到不平衡节点的左子树(Left)的右子树(Right),导致不平衡节点的平衡因子由1变为2 |
RL 右左情况 | 插入一个新节点到不平衡节点的右子树(Right)的左子树(Left),导致不平衡节点的平衡因子由-1变为-2 |
2.4.1左平衡
void LeftBalance(Tree *T){
Tree L,Lr;
L=(*T)->lchild;
switch(L->bf){
case LH:
(*T)->bf=L->bf=EH;
R_Rotate(T);
break;
case RH;
Lr=L->rchild;
switch(Lr->bf){
case LH://1
(*T)->bf=RH;
L->bf=EH;
break;
case EH://0
(*T)->bf=L->bf=EH;
break;
case RH://-1
(*T)->bf=EH;
L->bf=LH;
break;
}
Lr->bf=EH;
L_Rotate(&(*T)->lchild);
R_Rotate(T);
}
}
2.4.1右平衡
void LeftBalance(Tree *T){
Tree L,Ll;
L=(*T)->rchild;
switch(L->bf){
case RH:
(*T)->bf=L->bf=EH;
L_Rotate(T);
break;
case LH;
Ll=L->lchild;
switch(Ll->bf){
case LH://1/??????
(*T)->bf=LH;
L->bf=EH;
break;
case EH://0
(*T)->bf=L->bf=EH;
break;
case RH://-1//?????
(*T)->bf=EH;
L->bf=RH;
break;
}
Ll->bf=EH;
R_Rotate(&(*T)->lchild);
L_Rotate(T);
}
}
2.5插入
typedef struct BiTNode{
int data;
int bf;
struct BitNode *lchild; *rchild;
}Node,*Tree;
int Insert_AVL(Tree *T,int e,int *taller){
if(!*T){
*T=(Tree)malloc(sizof(Node));
(*T)->lchild=NULL;
(*T)->Nchild=NULL;
(*T)->bf=EH;
*taller=TRUE;
}else{
if(e==(*T)0>data){
*taller=FALSE;
return FALSE;
}
if(e<(*T)->data){
if(!Insert_AVL(&(*T)->lchild, e,taller)){
return FALSE;
}
if(*taller){
switch((*T)->bf){
case LH://1
LeftBalance(T);//左平衡操作
*taller=FALSE;
break;
case EH://本身是平衡的所以插入左变 就将不平衡
(*T)->bf=LH;
*taller=TRUE;
break;
case RH://-1
(*T)->bf=EH;
*taller=FALSE;
break;
}
}
}else{
if(!Insert_AVL(&(*T)->rchild, e,taller)){
return FALSE;
}
if(*taller){
switch((*T)->bf){
case LH://1
(*T)->bf=EH;
*taller=FALSE;
break;
case EH://本身是平衡的所以插入左变 就将不平衡
(*T)->bf=RH;
*taller=TRUE;
break;
case RH://-1
RightBalance(T);//右平衡操作
*taller=FALSE;
break;
}
}
}
}
}