zoukankan      html  css  js  c++  java
  • 二叉树的操作

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

  • 相关阅读:
    SpringBoot
    mysql 8版本使用注意
    RocketMQ服务搭建_1
    otter使用
    greenplum
    一、Linux概述 二、Linux的安装 三、Linux的常用命令(重点)
    一、DAO设计模式 二、DAO设计模式的优化 三、JDBC中的事务,连接池的使用
    一、JDBC的概述 二、通过JDBC实现对数据的CRUD操作 三、封装JDBC访问数据的工具类 四、通过JDBC实现登陆和注册 五、防止SQL注入
    一、MySQL中的索引 二、MySQL中的函数 三、MySQL数据库的备份和恢复 四、数据库设计和优化(重点)
    一、TCL事务控制语言 二、MySQL中的约束 三、多表查询(重点) 四、用户的创建和授权 五、MySQL中的索引
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/11031969.html
Copyright © 2011-2022 走看看