- 题目链接 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