九度OJ 1541 二叉树【数据结构】

题目地址:http://ac.jobdu.com/problem.php?pid=1541

题目描述:

旋转是二叉树的基本操作,我们可以对任意一个存在父亲节点的子节点进行旋转,包括如下几种形式(设被旋转节点为x,其父亲节点为p):
1.左旋
旋转前,x是p的右儿子。
x的左儿子(若存在)变为p的右儿子,p变为x的左儿子。如下图

2.右旋
旋转前,x是p的左儿子。
x的右儿子(若存在)变为p的左儿子,p变为x的右儿子。如下图

综上,我们可以通过检查选择前x是p的左儿子还是右儿子来判断该次旋转是左旋还是右旋。

给定一颗n个节点的二叉树,其节点由1至n编号,并给定一系列操作,如下:
1.rotate x,对编号x的节点进行旋转,若x为根节点,则不进行任何操作。
2.parent x,输出编号x的父亲节点编号,若x为根节点输出-1。
3.size x,输出以x为根节点的子树的节点个数。

输入:

输入包含多组测试用例。
每组测试用例开头为一个整数n(1<=n<=1000),代表二叉树的节点个数。
接下去n行描述,二叉树原始的状态,第i行为两个整数x,y,代表i号节点的左儿子节点为x号节点,右儿子节点为y号节点,若x或y为-1,则表示相应儿子节点不存在。编号的范围为1到n。
接下去一行为一个整数t(1<=t<=50000),代表操作的个数。
最后t行,每行代表一个对二叉树的操作,描述如上所示。

输出:

对于每组测试用例,输出操作parent x和size x查询的数据。

样例输入:
5
2 3
-1 -1
4 5
-1 -1
-1 -1
5
size 1
rotate 5
size 5
parent 3
parent 4
样例输出:
5
3
5
3

#include <stdio.h>
#include <string.h>
 
typedef struct node{
    int parent;
    int left;
    int right;
}Node;
 
Node tree[1001];
int has_parent[1001];
int size[1001];
int n;
int root;
 
int Compute(int node){
    return (node == -1) ? 0 : size[node];
}
 
int Size(int node){
    if (node == -1)
        return 0;
    if (tree[node].left != -1)
        size[tree[node].left] = Size(tree[node].left);
    if (tree[node].right != -1)
        size[tree[node].right] = Size(tree[node].right);
    return size[node] = Compute(tree[node].left) + Compute(tree[node].right) + 1; 
}
 
void Rotate(int node){
    int parent, grandpar;
    int left, right;
    if (node != root){
        parent = tree[node].parent;
        grandpar = tree[parent].parent;
        tree[node].parent = grandpar;
        if (grandpar != -1){
            if (tree[grandpar].right == parent)
                tree[grandpar].right = node;
            else
                tree[grandpar].left = node;
        }
        if (parent == root)
            root = node;
        tree[parent].parent = node;
        if (tree[parent].right == node){//node是其父节点的右孩子,左旋 
            left = tree[node].left;
            tree[parent].right = left;
            tree[node].left = parent;
            if (left != -1){
                tree[left].parent = parent;
            }
        }
        else{//node是其父节点的左孩子,右旋 
            right = tree[node].right;
            tree[parent].left = right;
            tree[node].right = parent;
            if (right != -1){
                tree[right].parent = parent;
            }
        }
        size[node] = size[parent];
        size[parent] = Compute(tree[parent].left) + Compute(tree[parent].right) + 1;
    }
}
 
int main(void) {
    int i;
    int t;
    char ope[10];
    int id;
     
    while (scanf("%d", &n) != EOF){
        for (i = 1; i <= n; ++i){
            memset(has_parent, 0, sizeof(has_parent));
            memset(size, 0, sizeof(size));
            scanf("%d%d", &tree[i].left, &tree[i].right);
            if (tree[i].left != -1){
                tree[tree[i].left].parent = i;
                has_parent[tree[i].left] = 1;
            }   
            if (tree[i].right != -1){
                tree[tree[i].right].parent = i;
                has_parent[tree[i].right] = 1;
            }
        }
        for (i = 1; i <= n; ++i)
            if (has_parent[i] != 1){
                tree[i].parent = -1;
                root = i;
                break;
            }
        for (i = 1; i <= n; ++i)
            Size(i);
        scanf("%d", &t);
        while (t-- != 0){
            scanf("%s%d", ope, &id);
            if (ope[0] == 'r')
                Rotate(id);
            else if (ope[0] == 'p')
                printf("%d\n", tree[id].parent);
            else
                printf("%d\n", size[id]);
        }
    }
     
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值