题目地址: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;
}

九度OJ 1541 二叉树【数据结构】的更多相关文章

  1. 九度oj 1541 二叉树

    原题链接:http://ac.jobdu.com/problem.php?pid=1541 简答题如下: #include<algorithm> #include<iostream& ...

  2. 九度oj 1184 二叉树遍历

    原题链接:http://ac.jobdu.com/problem.php?pid=1184 简单的二叉树重建,遍历. 如下: #include<cstdio> #include<cs ...

  3. [九度OJ]1078.二叉树的遍历(重建)

    原题链接:http://ac.jobdu.com/problem.php?pid=1078 题目描述: 二叉树的前序.中序.后序遍历的定义:前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其 ...

  4. [九度OJ]1113.二叉树(求完全二叉树任意结点所在子树的结点数)

    原题链接:http://ac.jobdu.com/problem.php?pid=1113 题目描述: 如上所示,由正整数1,2,3……组成了一颗特殊二叉树.我们已知这个二叉树的最后一个结点是n.现在 ...

  5. 九度OJ 1113 二叉树

    题目地址:http://ac.jobdu.com/problem.php?pid=1113 题目描述: 如上所示,由正整数1,2,3……组成了一颗特殊二叉树.我们已知这个二叉树的最后一个结点是n.现在 ...

  6. 九度OJ 1078 二叉树遍历

    题目地址:http://ac.jobdu.com/problem.php?pid=1078 题目描述: 二叉树的前序.中序.后序遍历的定义: 前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历 ...

  7. 九度oj 1521 二叉树的镜像

    原题链接:http://ac.jobdu.com/problem.php?pid=1521 水题,如下.. #include<algorithm> #include<iostream ...

  8. 【九度OJ】题目1113:二叉树 解题报告

    [九度OJ]题目1113:二叉树 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1113 题目描述: 如上所示,由正整数1,2,3-- ...

  9. 【九度OJ】题目1078:二叉树遍历 解题报告

    [九度OJ]题目1078:二叉树遍历 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1078 题目描述: 二叉树的前序.中序.后序遍历 ...

随机推荐

  1. lightOJ 1030(期望)

    题意:有一个迷宫是1×n的格子,一个人每到一个格子就能够把这个格子内的金子所有拿走,刚開始站在第1个格子,然后開始掷骰子得到点数x,他就要从当前位置走到加x的位置.假设发现位置是大于n的就又一次掷骰子 ...

  2. 硬盘安装centos

    1.用pqmagic划分出来二个分区,第一个是ext3格式的,用于放centos镜像文件,第二个不用管是什么格式的,用于安装centos,我一般在磁盘最后面划分出来二个分区. 2.安装Ext2Fsd  ...

  3. 一种快速求fibonacci第n个数的算法

    利用动态规则的思路,摒弃传统的递归做法,可以得到一种快速的求fibonacci第n个数的算法: ''' 求第n(从1开始)位fibonacci数 fibonacci数列前两位为0, 1. 后面每一位数 ...

  4. IIS 允许无后缀文件访问的配置

    最近一个项目 前端开发用了一大堆无后缀的html模板,问题就是发布到IIS以后访问 模板文件报404错误.无法下载. 百度 谷歌 搜一堆 都是MIME里添加 '.*' 实际上无效 正解是: MIME里 ...

  5. nginx.conf配置及优化相关

    nginx.conf配置文件内容 user www www; worker_processes ; worker_rlimit_nofile ; error_log /data/nginx/logs/ ...

  6. iOS 成员变量,实例变量,属性变量的区别,联系

    在ios第一版中: 我们为输出口同时声明了属性和底层实例变量,那时,属性是oc语言的一个新的机制,并且要求你必须声明与之对应的实例变量,例如: 注意:(这个是以前的用法) @interface MyV ...

  7. Windows 平台下Git 服务器搭建

    由于项目中一直在使用git作为版本管理,自己对git的理解.使用都还不是怎么的熟悉,所以准备深入了解一下git及一些常用命令的使用,于是干脆把服务端架上,通过自己的PC作为服务端同时作为客户端的角色进 ...

  8. 用Gradle 构建android程序

    前言 android gradle 的插件终于把混淆代码的task集成进去了,加上最近,android studio 用的是gradle 来构建项目, 下定决心把android gralde 构建项目 ...

  9. Android布局中的空格以及占一个汉字宽度的空格的实现

    在Android布局中进行使用到空格,以便实现文字的对齐.那么在Android中如何表示一个空格呢? 空格:  窄空格:  一个汉字宽度的空格:   [用两个空格(  )占一个汉字的宽度时,两个空格比 ...

  10. 不可小觑的“alt”

    定义和用法 alt 属性是一个必需的属性,它规定在图像无法显示时的替代文本. 假设由于下列原因用户无法查看图像,alt 属性可以为图像提供替代的信息: 网速太慢 src 属性中的错误 浏览器禁用图像 ...