数据结构实验之查找二:平衡二叉树
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
****************************************************/