PAT1102翻转二叉树

1102 Invert a Binary Tree (25分)

The following is from Max Howell @twitter:

Google: 90% of our engineers use the software you wrote (Homebrew), but you can't invert a binary tree on a whiteboard so fuck off.


      
    

Now it’s your turn to prove that YOU CAN invert a binary tree!

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤10) which is the total number of nodes in the tree – and hence the nodes are numbered from 0 to N−1. Then N lines follow, each corresponds to a node from 0 to N−1, and gives the indices of the left and right children of the node. If the child does not exist, a - will be put at the position. Any pair of children are separated by a space.

Output Specification:

For each test case, print in the first line the level-order, and then in the second line the in-order traversal sequences of the inverted tree. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line.

Sample Input:

8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6


      
    

Sample Output:

3 7 2 6 4 0 5 1
6 5 7 4 3 2 0 1

题目大意:

给定一棵二叉树,让我们把二叉树进行翻转,所谓翻转,就是对于每一棵子树的根节点来说,我们需要交换其左右孩子。也就是,交换完的二叉树和原来的树应该是镜像对称的。题目要求我们输出翻转后的二叉树的层序遍历和中序遍历。

思路分析:

这里面主要需要解决翻转的问题。而解决翻转通常使用后序递归遍历。在遍历回溯的过程中进行交换左右子树的操作。说到这里,我们首先需要考虑的一个问题是,如何存储题目给定的这一棵二叉树。由于题目每一行输入是一个节点,而这些节点的输入并没有按照 二叉树链式存储的格式给定,说人话就是,在读入整棵树的信息之前,您并不知道这棵树的结构,我们知道如果使用链式存储,会给我们的编程带来很大麻烦。 一个比较简单的做法就是使用对象数组存储,数组的下标正好可以作为节点的 val 值。每一个数组元素存储一个Node对象,通过Node 对象的left 和 right 找到这个节点的左右孩子在数组中的位置。 比如,节点3 的left 为 1 那么我们就是知道 1号节点就是3号节点的左孩子。

如何确定哪个节点是root(根) 节点呢?因为我们的节点编号都是从 0 --N-1的 ,因次(不是任何节点的孩子节点)就是根节点。因次,我们可以设置一个boolean数组,在读取每一个节点的孩子节点数据时,在相应的boolean数组的位置标记为true 表示这个位置的节点不是一个根节点,因为它都是别人孩子了。对于空节点我们设置为-1 这样也是因为数组下标没有-1 比较容易判断。

01234567
Left 1Left -1left 0left 2Left -1left -1left 5left 4
right -1Right -1Right -1right 7Left -1Right -1Right -1right 6

在读取数据的时候进行标记,我们会把除了 3位置以外的位置都标记为 true ,这样在后面寻找根节点的时候,false位置只有 3号位置。我们就知道 3号是根节点。 剩下的遍历其实是比较容易掌握的。我们重点就是用数组建立静态的二叉树

完整代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

//8
//1 -
//- -
//0 -
//2 7
//- -
//- -
//5 -
//4 6
public class  Main {
    static class Node {
        int left;
        int right;

        public Node(int left, int right) {
            this.left = left;
            this.right = right;
        }
    }

    static int nums;
    static int cnts = 0;
    static boolean[] notRoot;
    static Node[] nodes;

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        nums = Integer.parseInt(bf.readLine().trim());
        nodes = new Node[nums];

        notRoot = new boolean[nums];
        // 建立静态二叉树 数组中一个位置一个节点
        for (int i = 0; i < nums; i++) {
            String[] info = bf.readLine().trim().split(" ");
            nodes[i] = new Node(-1, -1);
            if (!info[0].equals("-")) {
                nodes[i].left = Integer.parseInt(info[0]);
                notRoot[nodes[i].left] = true;
            }
            if (!info[1].equals("-")) {
                nodes[i].right = Integer.parseInt(info[1]);
                notRoot[nodes[i].right] = true;
            }
        }
        int root = -1;  // 寻找根节点
        for (int i = 0; i < nums; i++) {
            if (!notRoot[i]) {
                root = i;
                break;
            }
        }

        invert(root); // 翻转二叉树
        LevelOrder(root); // 层序遍历
        cnts = 0; // 让cnts 归0 应为层序用了一次cnts自曾,控制空格输出 现在需要再用一次
        System.out.println(); // 输出换行
        InorderTraver(root); // 中序遍历
    }

    // 翻转二叉树
    static void invert(int root) {
        if (root == -1) // 这是一个空节点,因为我们的节点编号是从 0 .....nums-1
            return;
        invert(nodes[root].left); // 递归翻转左子树
        invert(nodes[root].right); // 递归翻转右子树
        int left = nodes[root].left;    // 下面四行是左右孩子互换,交换都是发生在递归的回溯过程中
        int right = nodes[root].right;
        nodes[root].left = right;
        nodes[root].right = left;
    }

    // 二叉树的中序遍历
    static void InorderTraver(int root) {
        if (root == -1)
            return;
        InorderTraver(nodes[root].left);
        System.out.print(root);
        cnts++;
        if (cnts != nums)
            System.out.print(" ");
        InorderTraver(nodes[root].right);

    }

    // 二叉树的层序遍历
    static void LevelOrder(int root) {
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(root);

        while (!queue.isEmpty()) {
            int val = queue.poll();
            System.out.print(val);
            cnts++;
            if (cnts != nums)
                System.out.print(" ");

            if (nodes[val].left != -1)
                queue.offer(nodes[val].left);
            if (nodes[val].right != -1)
                queue.offer(nodes[val].right);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值