AVL平衡二叉树

数据结构实验之查找二:平衡二叉树
Time Limit: 400 ms Memory Limit: 65536 KiB

Problem Description
根据给定的输入序列建立一棵平衡二叉树,求出建立的平衡二叉树的树根。

Input
输入一组测试数据。数据的第1行给出一个正整数N(n <= 20),N表示输入序列的元素个数;第2行给出N个正整数,按数据给定顺序建立平衡二叉树。

Output
输出平衡二叉树的树根。

Sample Input
5
88 70 61 96 120
Sample Output
70
Hint

Source
xam

#include<bits/stdc++.h>
using namespace std;
typedef struct node
{
    int data;
    int deep;
    struct node *l, *r;
} node;

int Max(int a, int b)
{
    return a > b ? a : b;
}

int Deep(node *t)
{
    if(!t)
        return -1;///如果要返回0的话,那么最底层的层数就会从1开始,因为考虑到是从下层往上层返回逐层递加,
                  ///而且是左右(相减)比较完之后再层数加一,所以最重要的地方就在这里,详见最下方解析
    return t->deep;
}

node *LL(node *t)///右旋
{
    node *p = t->l;///用一个指针接上中间数节点
    t->l = p->r;///最大数节点的左孩子接上中间数节点的右孩子(一般是接上NULL,如果中间数节点右孩子有值也就完成了指针域的变换)
    p->r = t;///将中间数节点的右孩子接成最大数节点
    t->deep = Max(Deep(t->l), Deep(t->r)) + 1;
    p->deep = Max(Deep(p->l), Deep(p->r)) + 1;///这里有点问题,p->r 不是已经接成 t了吗,deep会不会改变?
    return p;
}

node *RR(node *t)///左旋
{
    node *p = t->r;
    t->r = p->l;
    p->l = t;
    t->deep = Max(Deep(t->l), Deep(t->r)) + 1;
    p->deep = Max(Deep(p->l), Deep(p->r)) + 1;
    return p;
}

node *LR(node *t)///先左旋再右旋
{
    t->l = RR(t->l);
    return LL(t);
}

node *RL(node *t)///先右旋再左旋
{
    t->r = LL(t->r);
    return RR(t);
}

node *creat(node *t, int n)///插入创建
{
    if(!t)///值的插入
    {
        t = new node;
        t->data = n;
        t->deep = -1;
        t->l = t->r = NULL;///左右指针域放空,方便插入和旋转操作
    }
    else
    {
        if(n < t->data)///当前值小于根值 (会出现的问题一定是LL 或 LR)
        {

            ///***这个递归创建很关键(每次都要改变deep值,每次不平衡都会调整)
            t->l = creat(t->l, n);///进入左子树创建


            if(Deep(t->l) - Deep(t->r) > 1)///一旦不平衡
            {
                ///这里要说明一下,一旦出现不平衡,最底层和操作层就一定是老师讲的那个最简模型
                if(t->l->data > n)///如果中间值大于n 就说明是 LL
                    t = LL(t);
                else
                    t = LR(t);///否则就是LR
            }
        }


        else///*****这里用else if也许会出错,遇见相等的会直接不进入,相当于相同的数字被直接删除
        {

            ///***这个递归创建很关键(每次都要改变deep值,每次不平衡都会调整)
            t->r = creat(t->r, n);


            if(Deep(t->r) - Deep(t->l) > 1)
            {
                if(t->r->data < n)
                    t = RR(t);
                else
                    t = RL(t);
            }
        }
    }
    t->deep = Max(Deep(t->l), Deep(t->r)) + 1;///全部操作结束之后改变根的平衡因子
    ///这里的深度与老师所说的不同的原因:不是通过左子树减去右子树,而是通过层层相加得到,有必要写一种相减得来的
    return t;
}

void zhong(node *root)
{
    if(root)
    {
        zhong(root->l);
        cout << root->data << " ";
        zhong(root->r);
    }
}

int main()
{
    int n, m;
    node *t = NULL;
    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> m;
        t = creat(t, m);
    }
    cout << t->data << endl;
///   zhong(t);
///   cout << endl;
    return 0;
}

///August
///1.考虑到顶层与空的比较,举例来说:3 2 1这三个数,会执行一次LL,执行的前一步比较时,三个节点的deep值分别是:最底层的1-->0, 中间的2-->1, 顶层的3-->1   <<-不是2--!!!!!
///顶层的3的deep值是1而不是2 !!!!!!
///2.这里就相当巧妙了,不是像老师说的那样,空就是0,而且最底层deep值也是0,设成-1是有根据的

///3.考虑到了层数的加一是在最后,而旋转的进行时在加一之前
///为了当deep值为1 时就可以 将其 与-1相减,导致差值为2,大于1,这样就可以顺利地进行旋转了

///December
///之前8月份的想法还是有问题的,这里更正一下,第一句第二句都是错误的,第三局是对的,其实改成return 0也可以

///以前的错误想法是说不这么写就会错,其实没有错,只是改变层数的表示方式

///比如输入1 2 3 ,这里必须要搞清楚和强调的点是<旋转是在上一级层数变换之前完成>
///输入 1   1 ---> 1
///输入 2   2 ---> 1  1 ---> 2
///输入 3   3 ---> 1  2 ---> 2 但是回到1的时候 RR判断成立,开始旋转,也就是说这时候的1的层数还没有被赋值
///旋转都是比较子节点的深度来判断的


/***************************************************
User name: 
Result: Accepted
Take time: 0ms
Take Memory: 248KB
Submit time: 2017-12-23 20:44:57
****************************************************/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值