1616. 判断完全 AVL 树

题目链接

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
1.二叉树的层次遍历
2.node的插入:在线算法
3.二叉平衡树的调整:
包括LL,RR,LR,RL。
4.insert函数需要多看两眼
5.获取平衡因子和高度的时候特殊判断结点为NULL的情况。


insert(BTNode *bt,int key)每次都是从根节点进入树,根据key关键字找对应位置。当新建的结点是当前节点的左孩子或右孩子时,高度差为1不会出现不平衡现象。不平衡只会出现在三层的时候,像LL,RR最简单的情况。insert的时候是递归插入的,由爷结点进入父节点,再有父节点进入子节点,子节点和父节点不会出现不平衡,但是子节点和爷结点可能会出现不平衡(因为新加了子节点),所以需要判断是否出现了不平衡,以及出现的是什么不平衡。

LL型A>B>C
在这里插入图片描述
LR型A>C>B,
所以根据B C的大小判断是LL还是LR。而在B的时候是不会判断出来不平衡的,只有递归退到A的时候才发现A的平衡因子大于1,所以就需要判断A的左孩子和这次新插入的C的key的大小。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N = 21;
typedef struct node{
    int key;
    struct node *lchild;
    struct node *rchild;
    int height;
}BTNode;
BTNode *bt;
int a[N];

//获取当前结点的高度 
int height(BTNode *bt)
{
	if(bt==NULL)return 0;
	return bt->height;
}
//获取当前节点的平衡因子 
int getbalance(BTNode *bt)
{
	if(bt==NULL)return 0;
	return height(bt->lchild)-height(bt->rchild);
}
//创建新的结点
BTNode *newnode(int key)
{
	BTNode *bt;
	bt=(BTNode *)malloc(sizeof(BTNode));
	bt->key=key;
	bt->height=1;
	bt->lchild=bt->rchild=NULL;
	return bt;
 } 
//LL 
BTNode *ll_rotate(BTNode *y)
{
	BTNode *x=y->lchild;
	y->lchild=x->rchild;
	x->rchild=y;
	y->height=max(height(y->lchild),height(y->rchild))+1;
	x->height=max(height(x->lchild),height(x->rchild))+1;
	return x;
}
BTNode *rr_rotate(BTNode *y)
{
	BTNode *x=y->rchild;
	y->rchild=x->lchild;
	x->lchild=y;
	y->height=max(height(y->lchild),height(y->rchild))+1;
	x->height=max(height(x->lchild),height(x->rchild))+1;
	return x;
}
BTNode *lr_rotate(BTNode *y)
{
	BTNode *x=y->lchild;
	y->lchild=rr_rotate(x);
	return ll_rotate(y);
}
BTNode  *rl_rotate(BTNode *y)
{
	BTNode *x=y->rchild;
	y->rchild=ll_rotate(x);
	return rr_rotate(y);
}
BTNode *insert(BTNode *bt,int key)
{
	//构建二叉排序树 
	if(bt==NULL)
		return newnode(key);
	if(key<bt->key)
		bt->lchild=insert(bt->lchild,key);
	else if(key>bt->key)
		bt->rchild=insert(bt->rchild,key);
	else return bt;

	bt->height=1+max(height(bt->rchild),height(bt->lchild));//调整高度 
	//调整
	int balance=getbalance(bt);
	if(balance>1&&key < bt->lchild->key)//LL型
	{
		return ll_rotate(bt); 
	 } 
	 
	else if(balance<-1&&key > bt->rchild->key)
		return rr_rotate(bt);
		
	else if(balance>1&&key > bt->lchild->key)
		return lr_rotate(bt);
		
	else if(balance<-1&&key < bt->rchild->key)
		return rl_rotate(bt);
		
	return bt;
}
void cengci(BTNode *bt)
{
	int sum=0;
	int left=0,right=0,flag=1;
    queue<BTNode *> q;
    q.push(bt);
    if(q.empty()) cout<<"Yes";
    while(!q.empty())
    {
        BTNode *p=q.front();
        q.pop();
			sum++;
        printf("%d ",p->key);
        if(p->lchild!=NULL)
            q.push(p->lchild);
        else left=1;
        if(p->rchild!=NULL)
           	 q.push(p->rchild);
		else right=1;
		if((left==1&&p->lchild!=NULL)||(right==1&&p->rchild!=NULL))
			flag=0;
    }
    if(flag==0)
    	cout<<endl<<"NO"; else cout<<endl<<"YES";
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
    	  scanf("%d",&a[i]);
    	  bt=insert(bt,a[i]);
	}
	cengci(bt);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值