二叉树的操作

题目链接http://dsalgo.openjudge.cn/binarytree/10/
总时间限制: 1000ms 内存限制: 65535kB
描述

给定一棵二叉树,在二叉树上执行两个操作:
1. 节点交换
把二叉树的两个节点交换。

2. 前驱询问
询问二叉树的一个节点对应的子树最左边的节点。

输入第一行输出一个整数t(t <= 100),代表测试数据的组数。

对于每组测试数据,第一行输入两个整数n m,n代表二叉树节点的个数,m代表操作的次数。

随后输入n行,每行包含3个整数X Y Z,对应二叉树一个节点的信息。X表示节点的标识,Y表示其左孩子的标识,Z表示其右孩子的标识。

再输入m行,每行对应一次操作。每次操作首先输入一个整数type。

当type=1,节点交换操作,后面跟着输入两个整数x y,表示将标识为x的节点与标识为y的节点交换。输入保证对应的节点不是祖先关系。

当type=2,前驱询问操作,后面跟着输入一个整数x,表示询问标识为x的节点对应子树最左的孩子。

1<=n<=100,节点的标识从0到n-1,根节点始终是0.
m<=100输出对于每次询问操作,输出相应的结果。

样例输入

2
5 5
0 1 2
1 -1 -1
2 3 4
3 -1 -1
4 -1 -1
2 0
1 1 2
2 0
1 3 4
2 2
3 2
0 1 2
1 -1 -1
2 -1 -1
1 1 2
2 0

样例输出

1
3
4
2

 

 

问题分析

从样例数据可知,若是节点 i 没有左孩子或右孩子节点,那么输入数据时节点 i 的相应孩子的编号就是-1.

另外,题目中强调节点编号就是0~n-1,所以用数组存放即可。

最后需要注意的是:题目描述的操作类型一里面,交换了2号节点和3号节点(如下图所示),看似没有改变树的结构。但其实二叉树的左右孩子节点是有顺序的,并不能随便调换。所以下图调换了2号和3号节点后,1号节点的左孩子和右孩子节点就发生了变化。

另外,交换了x号与y号节点以后,以x和y作为根的子树也跟着x和y移动的。如上图所示。

所以交换x和y号节点时需要分析x、y是左孩子还是右孩子,然后相应地修改x的父节点、y的父节点两者相应子节点的映射目标。

 

至于第二个问题,直接向左下角搜索寻找最靠左下角的节点就是答案。

完整代码如下:

 1 #include <stdio.h>
 2 int a[102][3];//a[i][0]表示节点i的左孩子节点编号,a[i][1]表示节点i的右孩子节点编号;a[i][2]表示i节点的父节点编号。 
 3 int main()
 4 {
 5     int t,n,m;
 6     int x,y,z,type;
 7     int i,j;
 8     freopen("data.in","r",stdin);
 9     //freopen("data.out","w",stdout);
10     scanf("%d",&t);
11     for(i=0;i<t;i++)
12     {
13         scanf("%d%d",&n,&m);
14         for(j=0;j<n;j++) a[j][0]=a[j][1]=a[j][2]=0;
15         
16         for(j=0;j<n;j++)
17         {
18             scanf("%d%d%d",&x,&y,&z);
19             if(y>0)
20             {
21                 a[x][0]=y;    //x节点的左孩子节点分y
22                 a[y][2]=x;    //y和z节点的父节点都是x 
23             }
24             if(z>0)
25             {
26                 a[x][1]=z;    //x节点的右孩子节点z 
27                 a[z][2]=x;    //y和z节点的父节点都是x 
28             }
29         }
30         
31         for(j=0;j<m;j++)
32         {
33             scanf("%d",&type);
34             if(type==1)
35             {
36                 scanf("%d%d",&x,&y);
37                 int rootX=a[x][2];
38                 int rootY=a[y][2];
39                 if(a[rootX][0]==x)//x是rootX的左孩子节点
40                 {
41                     if(a[rootY][0]==y)//y是rootY的左孩子节点
42                     {
43                         a[rootX][0]=y;  a[x][2]=rootY;
44                         a[rootY][0]=x;  a[y][2]=rootX;
45                     }
46                     else   //y是rootY的右孩子节点
47                     {
48                         a[rootX][0]=y;  a[x][2]=rootY;
49                         a[rootY][1]=x;  a[y][2]=rootX;
50                     }
51                 }
52                 else   //x是rootX的右孩子节点
53                 {
54                     if(a[rootY][0]==y)//y是rootY的左孩子节点
55                     {
56                         a[rootX][1]=y;  a[x][2]=rootY;
57                         a[rootY][0]=x;  a[y][2]=rootX;
58                     }
59                     else   //y是rootY的右孩子节点
60                     {
61                         a[rootX][1]=y;  a[x][2]=rootY;
62                         a[rootY][1]=x;  a[y][2]=rootX;
63                     }
64                 }/**/
65             }
66             else
67             {
68                 scanf("%d",&x);
69                 while(a[x][0]!=0)
70                 {
71                     x=a[x][0];
72                 }
73                 printf("%d\n",x);/**/
74             }
75         }
76     }
77     return 0;
78 }

 

代码中,type==1时的嵌套if语句是要讨论类似如下图所示的情况:

讨论以下四种情况下,交换x和y节点的操作

(1)x=4,y=6

(2)x=4,y=7

(3)x=5,y=6

(4)x=5,y=7

 

posted on 2019-06-16 16:35  华山青竹  阅读(1162)  评论(0编辑  收藏  举报

导航