PAT_A 1123. Is It a Complete AVL Tree (30)

1123. Is It a Complete AVL Tree (30)

An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.

Now given a sequence of insertions, you are supposed to output the level-order traversal sequence of the resulting AVL tree, and to tell if it is a complete binary tree.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (<= 20). Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, insert the keys one by one into an initially empty AVL tree. Then first print in a line the level-order traversal sequence of the resulting AVL tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line. Then in the next line, print “YES” if the tree is complete, or “NO” if not.
Sample Input 1:

5
88 70 61 63 65

Sample Output 1:

70 63 88 61 65
YES

Sample Input 2:

8
88 70 61 96 120 90 65 68

Sample Output 2:

88 65 96 61 70 90 120 68
NO

补充几个测试
Sample Input
16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Sample output
8 4 12 2 6 10 14 1 3 5 7 9 11 13 15 16
NO

  • code:这种题就是题意明确,直接考算法。

    • 二叉树的层序遍历,使用队列即可(如果需要分层,则可用 last nlast两个指针来实现,当当前节点和last相等时,本层结束,置last=nlast,nlast一直指向queue的最后一个。)
    • 构造avl树(调整:向左转,向右转,左右转,右左转。注意破坏平衡后,调整时,需要对整个树进行,仅仅调整插入的那点有时仍是不平衡的),全局调整
    • 判断是否是完全二叉树(标记:左孩子的标记=父亲的二倍,右孩子等于父亲的二倍+1,根的标记为1。判断最后一个节点的标记是否和节点数相等,若等则是,否则相反)。
  • code:

#include<iostream>
#include<queue>
using namespace std;
int N;
struct tree
{
    //tree* p;没有记录父亲节点,本想对个p,方便操作,结果在调整是,被这个p弄的好晕
    tree* left;
    tree* right;
    int val;
    int flag;
};
tree *root=NULL;
//A B C
//还要向上返回的,向右转,仅调 A B
tree *rightRotate(tree*a)
{
    tree*b=a->left;
    a->left=b->right;
    b->right=a;
    return b;
}
//向左转,仅调 A B
tree* leftRotate(tree *a)
{
    tree* b=a->right;
    a->right=b->left;
    b->left=a;
    return b;
}
//逐渐向上调整
tree* leftRightRotate(tree*a)
{
//A B C
    //调整B C
    a->left=leftRotate(a->left);
    //调整A C
    return rightRotate(a);
}
tree *rightLeftRotate(tree*a)
{
    //调整B C
    a->right=rightRotate(a->right);
    //调整A C
    return leftRotate(a);
}
int getHeight(tree* a)
{
    if(a==NULL)
      return 0;
    else
    {
        int l=getHeight(a->left);
        int r=getHeight(a->right);
        return l>r?l+1:r+1;
    }
}
//不要记录父亲,只需要需要返回时来更新,使父亲指向孩子
//当a==NULL时,new的tree是传不出去的,
//当a不是NULL,对a的内容设置new的tree是可以传出去的
tree* insert(tree *a,int val)
{
    if(a==NULL)
    {
        //这个a从参数这传不出去
        a=new tree();
        a->left=NULL;
        a->right=NULL;
        a->val=val;
        return a;//只能返回去
    }
    //r
    if(val>a->val)
    {
        //返回时绑定
        a->right=insert(a->right,val);
        //插入后要调整了
        int l=getHeight(a->left);
        int r=getHeight(a->right);
        //若不平衡,递归返回时,会触发调整。返回到根,即对整体已调整完。
        if(r-l>=2)
        {
            //r r
            if(val>a->right->val)
            {
                a=leftRotate(a);
            }else
            {
                a=rightLeftRotate(a);
            }
        }
    }else if(val<a->val)
    {
        a->left=insert(a->left,val);
        //插入后要调整了
        int l=getHeight(a->left);
        int r=getHeight(a->right);
        if(l-r>=2)
        {
            //l r
            if(val>a->left->val)
            {
                a=leftRightRotate(a);
            }else
            {
                a=rightRotate(a);
            }
        }
    }
    return a;
}
bool output(tree *a)
{
    queue<tree*>que;
    que.push(a);
    int flag=1;
    a->flag=1;
    while(que.empty()==false)
    {
        if(que.front()->left!=NULL)
        {
            que.push(que.front()->left);
            que.front()->left->flag=que.front()->flag*2;
        }
        if(que.front()->right!=NULL)
        {
            que.push(que.front()->right);
            que.front()->right->flag=que.front()->flag*2+1;
        }
        cout<<que.front()->val;
        flag=que.front()->flag;
        que.pop();
        if(que.empty()==false)
          cout<<" ";
        else
          cout<<endl;
    }
    if(flag==N)
      return true;
    else
      return false;
}
int main()
{
    cin>>N;
    int tmp=0;
    for(int i=0;i<N;i++)
    {
        cin>>tmp;
        //insert
        root=insert(root,tmp);
    }
    if(output(root)==false)
      cout<<"NO"<<endl;
    else
      cout<<"YES"<<endl;
    return 0;
}

部分正确代码,问题在没有对全局进行调整,只调整了插入点的部分。上边参考的前两个代码都是递归调整的。


  • code
#include<iostream>
#include<queue>
using namespace std;
struct _tree
{
    _tree *l;
    _tree *r;
    _tree *p;
    int v;
    int h;
    int flag;
    _tree()
    {
        l=r=p=NULL;
        v=h=0;
        flag=0;
    }
};
int N;
_tree *root=NULL;
void ll(_tree *b)
{
    _tree* a=b->p;


    if(a->p!=NULL)
    {

        if(a->p->l==a)
          a->p->l=b;
        if(a->p->r==a)
          a->p->r=b;
    }
    b->p=a->p;

    //b->r有可能是NULL
    a->l=b->r;
    if(b->r!=NULL)
        b->r->p=a;
    b->r=a;
    a->p=b;

    if(b->p==NULL)
    {

      root=b;
    }
}
void lr(_tree *b)
{
    _tree* a=b->p;
    _tree* c=b->r;

    if(a->p!=NULL)
    {
        if(a->p->l==a)
          a->p->l=c;
        if(a->p->r==a)
          a->p->r=c;
    }

    //l
    b->r=c->l;
    if(c->l!=NULL)
      c->l->p=b;
    c->l=b;
    b->p=c;
    c->p=a;
    //r
    a->l=c->r;
    c->r=a;
    c->p=a->p;
    a->p=c;

    if(c->p==NULL)
    {
         root=c;
    }
}
void rl(_tree *b)
{
    _tree*a=b->p;
    _tree*c=b->l;

    if(a->p!=NULL)
    {
        if(a->p->l==a)
          a->p->l=c;
        if(a->p->r==a)
          a->p->r=c;
    }


    //r
    c->p=a;
    if(c->r!=NULL)
      c->r->p=b;
    b->l=c->r;
    c->r=b;
    b->p=c;
    //l
    c->p=a->p;
    a->p=c;
    a->r=c->l;
    c->l=a;
    if(c->p==NULL)
      root=c;
}
void rr(_tree *b)
{
    _tree*a=b->p;
    //1
    if(a->p!=NULL)
    {
        if(a->p->l==a)
          a->p->l=b;
        if(a->p->r==a)
          a->p->r=b;
    }
    b->p=a->p;
    //2
    a->p=b;

    a->r=b->l;

    if(b->l!=NULL)
        b->l->p=a;

    b->l=a;

    if(b->p==NULL)
      root=b;
}
int updateH(_tree *a)
{
    if(a==NULL)
      return 0;
    int tmp_a=updateH(a->l);
    int tmp_b=updateH(a->r);
    a->h=tmp_a-tmp_b;
    if(tmp_a>tmp_b)
      return tmp_a+1;
    else
      return tmp_b+1;
}
void avl(_tree*a)
{
    if(a==NULL)
      return;

    //if(a->h>-2&&a->h<2)
     // return;
    if(a->h==2)
    {
        if(a->l!=NULL)
        {
            if(a->l->h<-1||a->l->h>1)
              avl(a->l);
            else if(a->l->h==1)
            {
                //l l
                ll(a->l);
            }else if(a->l->h==-1)
            {
                //l r
                lr(a->l);
            }
        }
    } else if(a->h==-2)
    {
        if(a->r!=NULL)
        {
            if(a->r->h<-1||a->r->h>1)
            {
              avl(a->r);
            }
            else if(a->r->h==1)
            {
                //r l
                rl(a->r);
            }else if(a->r->h==-1)
            {
                //r r
                rr(a->r);
            }
        }
    }else if(a->h==1)
      avl(a->l);
    else if(a->h==-1)
      avl(a->r);
}
bool output(_tree *node);
void insertAt(_tree *a,_tree*b)
{
    //a:root b:insert
    if(a==NULL)
      return;
    if(b->v<a->v)
    {
        ++a->h;
        if(a->l==NULL)
        {
            a->l=b;
            b->p=a;
            updateH(root);
            avl(root);
            updateH(root);
        }else
            insertAt(a->l,b);
    }else
    {
        --a->h;
        if(a->r==NULL)
        {
            a->r=b;
            b->p=a;
            updateH(root);
            avl(root);
            //avl(a);
            updateH(root);
            }else
            insertAt(a->r,b);
    }
    //output(root);
}
void insert(int a)
{
    _tree *node=new _tree();
    node->v=a;
    node->h=0;
    if(root==NULL)
    {
        root=node;
        return;
    }else
        insertAt(root,node);
}
int a=1;
int b=0;

bool output(_tree *node)
{
    int tmp_last=0;
    queue<_tree*>myQue;
    myQue.push(node);
    tmp_last=node->flag;
    node->flag=1;
    while(myQue.empty()==false)
    {
        if(myQue.front()->l!=NULL)
        {
            if(b)
              a=0;
            myQue.push(myQue.front()->l);
            myQue.front()->l->flag=myQue.front()->flag*2;
        }else
          b=1;
        if(myQue.front()->r!=NULL)
        {
            if(b)
              a=0;

            myQue.push(myQue.front()->r);
            myQue.front()->r->flag=myQue.front()->flag*2+1;
        }else
          b=1;
        cout<<myQue.front()->v;
//      cout<<myQue.front()->v<<"=";
/*
        if(myQue.front()->p!=NULL)
            cout<<myQue.front()->p->v;
        else
          cout<<"-1";
          */
        tmp_last=myQue.front()->flag;
        myQue.pop();
        if(myQue.empty()==false)
          cout<<" ";
        else
        {
          cout<<endl;
          if(tmp_last==N)
            return true;
        }
    }
    return false;
}
int main()
{
    cin>>N;
    int tmp=0;
    for(int i=0;i<N;i++)
    {
        cin>>tmp;
        insert(tmp);
    }
    output(root);
    if(a)
      cout<<"YES"<<endl;
    else
      cout<<"NO"<<endl;
    /*
    if(output(root)==true)
      cout<<"YES"<<endl;
    else
      cout<<"NO"<<endl;
      */
    return 0;
}

  • outpu
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值