二叉樹的操做

題目連接 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輸出對於每次詢問操做,輸出相應的結果。spa

樣例輸入3d

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

樣例輸出code

1
3
4
2

 

 

問題分析blog

從樣例數據可知,如果節點 i 沒有左孩子或右孩子節點,那麼輸入數據時節點 i 的相應孩子的編號就是-1.內存

另外,題目中強調節點編號就是0~n-1,因此用數組存放便可。get

最後須要注意的是:題目描述的操做類型一里面,交換了2號節點和3號節點(以下圖所示),看似沒有改變樹的結構。但其實二叉樹的左右孩子節點是有順序的,並不能隨便調換。因此下圖調換了2號和3號節點後,1號節點的左孩子和右孩子節點就發生了變化。io

另外,交換了x號與y號節點之後,以x和y做爲根的子樹也跟着x和y移動的。如上圖所示。class

因此交換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

相關文章
相關標籤/搜索