这一题是根据输入,生成一棵二叉平衡搜索(AVL)树,然后输出其层次遍历,判断是否是完全二叉树,是输出YES,不是输出NO。
AVL树虽然知道,但是从来没写过,难点在于如何进行平衡,进行左旋右旋,有四种情况:
1、在左子树的左子树上插入导致不平衡,进行右旋操作。
2、在左子树的右子树上插入导致不平衡,进行先左旋后右旋操作。
3、在右子树的右子树上插入导致不平衡,进行左旋操作。
4、在右子树的左子树上插入导致不平凡,进行先右旋后左旋操作。
想了半天不知道怎么写,就拿出大学的书根据上面的代码敲了一遍,以为可以出来,结果有问题,改了老半天,主要还是对指针的使用不是很熟练。
看了一下别人的代码,是根据求左右子树的高度,然后求出当前的平衡因子,不平衡再根据条件进行平衡。书上的是直接根据当前的平衡因子出发判断,不好理解,需要动手画一画。
对于AVL树的操作,个人理解不是很到位,有时间还要好好研究研究。
判断是不是完全二叉树,可以在层次变量的时候判断,统计压入队列中的个数,当遇到节点没有子节点时,判断是否与n相同,即可知道是不是二叉树。
(用时:4:14:18.91)
#include <bits/stdc++.h>
using namespace std;
struct BTNode {
int value;
int bf;
BTNode *left,*right;
};
BTNode* RRoate(struct BTNode* p)
{
BTNode *lc = p->left;
p->left = lc->right;
lc->right = p;
p = lc;
return p;
}
BTNode* LRoate(struct BTNode* p)
{
BTNode *rc = p->right;
p->right = rc->left;
rc->left = p;
p = rc;
return p;
}
//左平衡
BTNode* leftBalance(BTNode* p)
{
BTNode *lc = p->left;
//为插入前的节点上平衡因子
switch(lc->bf) {
case 1:
p->bf = lc->bf=0;
p=RRoate(p);
break;
case -1://插入到左子树上的右子树节点
BTNode *rd = lc->right;
switch(rd->bf) {
case 1:
p->bf = -1;
lc->bf = 0;
break;
case 0:
p->bf = lc->bf = 0;
break;
case -1:
p->bf = 0;
lc->bf = 1;
break;
}
rd->bf = 0;
p->left=LRoate(lc);
p=RRoate(p);
break;
}
return p;
}
//右平衡
BTNode* RightBalance(BTNode* p)
{
BTNode *rc = p->right;
switch(rc->bf) {
case -1:
p->bf = rc->bf=0;
p=LRoate(p);
break;
case 1:
BTNode *ld = rc->left;
switch(ld->bf) {
case 1:
p->bf = 0;
rc->bf = -1;
break;
case 0:
p->bf = rc->bf = 0;
break;
case -1:
p->bf = 1;
rc->bf = 0;
break;
}
ld->bf = 0;
p->right=RRoate(rc);
p=LRoate(p);
break;
}
return p;
}
BTNode* InsertAVL(BTNode* root,int data,bool &taller)
{
if(!root) {
root = (BTNode*)malloc(sizeof(BTNode));
root->left = root->right = NULL;
root->value = data;
root->bf = 0;
taller= true;
} else {
if(data <= root->value ) {
root->left = InsertAVL(root->left,data,taller);
if(taller)//树变高了
switch(root->bf) {
case 1://左子树比右子树高
root=leftBalance(root);
taller = false;
break;
case 0:
root->bf = 1;
taller= true;
break;
case -1://右子树比左子树高
root->bf = 0;
taller = false;
break;
}
} else {
root->right = InsertAVL(root->right,data,taller);
if(taller)//树变高了
switch(root->bf) {
case 1:
root->bf = 0;
taller= false;
break;
case 0:
root->bf = -1;
taller= true;
break;
case -1:
root= RightBalance(root);
taller= false;
break;
}
}
}
return root;
}
int main()
{
int n;
scanf("%d",&n);
int data[n];
for(int i=0;i<n;i++){
scanf("%d",&data[i]);
}
BTNode *root= NULL;
bool taller = false;
for(int i=0;i<n;i++){
taller = false;
root=InsertAVL(root,data[i],taller);
}
bool first = 1;
bool isCompleted = true;
queue<BTNode*> que;
que.push(root);
int treeNum =1;
while(!que.empty()){
BTNode *p = que.front();
que.pop();
if(first){
printf("%d",p->value);
first = 0;
}
else{
printf(" %d",p->value);
}
if(p->left!=NULL){
que.push(p->left);
treeNum++;
}
else{
if(treeNum!=n){
isCompleted = false;
}
}
if(p->right!=NULL){
que.push(p->right);
treeNum++;
}
else{
if(treeNum!=n){
isCompleted = false;
}
}
}
printf("\n");
if(isCompleted){
printf("YES\n");
}
else{
printf("NO\n");
}
return 0;
}