数据结构与算法-BST(二叉搜索树)、AVL树(平衡二叉树)

1二叉查找树

1.1特点

  1. 任意节点的左子树不空, 则左子树上所有节点的key均小于它的根节点的key
  2. 任意节点的右子树不空, 则右子树上所有节点的key均大于它的根节点的key
  3. 任意节点的左,右子树也分别为二叉查找树
  4. 没有key相等的节点
  5. 二叉查找树进行中序遍历,可以得到一个递增的有序序列

在这里插入图片描述

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,左旋
在这里插入图片描述

旋转步骤:

  1. 获取旋转节点
  2. 旋转节点的子节点替换父节点的旋转节点
  3. 旋转节点父节点做旋转节点子节点
  4. 返回旋转节点

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;
				}
			}
		}
	}
}

2.6删除

发布了27 篇原创文章 · 获赞 4 · 访问量 1341

猜你喜欢

转载自blog.csdn.net/weixin_45639955/article/details/104262784