7. Binary Tree Serialization-二叉树的序列化和反序列化(BFS)

Description

设计一个算法,并编写代码来序列化和反序列化二叉树。将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”。

如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列化为一个字符串,并且可以将字符串反序列化为原来的树结构。

 注意事项

There is no limit of how you deserialize or serialize a binary tree, LintCode will take your output of serialize as the input of deserialize, it won't check the result of serialize.

样例

给出一个测试数据样例, 二叉树{3,9,20,#,#,15,7},表示如下的树结构:

  3
 / \
9  20
  /  \
 15   7

我们的数据是进行BFS遍历得到的。当你测试结果wrong answer时,你可以作为输入调试你的代码。

你可以采用其他的方法进行序列化和反序列化。

Solution

算法思路:

    1. 序列化:

    (1)BFS法访问二叉树左右节点,如果节点为空则序列化为#,如果不为空就将他的值加入StringBuilder中,且每个字符后面用逗号隔开。

    (2)最后移除末尾多余的“#”和“,”

    2. 反序列化:

    (1)先将序列化的字符串,取出中间部分,并用“,”分割为字符数组

    (2)取出第一个字符转换为int,并放入新生成的根节点中,创建队列,并加入root

    (3)循环字符串数组,如果不是#,就转换后左右依次添加为队首的左右儿子,并加入队列等待添加他的儿子节点

    (4)走到右节点之后,说明当前节点的左右节点信息已添加完毕,将待添加的TreeNode从队列中移除,准备添加下一节点

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */


public class Solution {
    /**
     * This method will be invoked first, you should design your own algorithm 
     * to serialize a binary tree which denote by a root node to a string which
     * can be easily deserialized by your own "deserialize" method later.
     */
    public String serialize(TreeNode root) {
        // write your code here
        //序列化,BFS访问二叉树左右节点,如果节点为空则序列化为#
        //如果不为空就将他的值加入StringBuilder中,每个字符后面用逗号隔开
        //移除末尾多余的“#”和“,”
        if (root == null) {
            return "{}";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if (node == null) {
                sb.append("#");
            } else {
                sb.append(node.val);
                queue.offer(node.left);
                queue.offer(node.right);
            }
            sb.append(",");
        }
        
         // remove tailing sharp and comma
         for (int i = sb.length() - 1; i >= 0; i--) {
             if (sb.charAt(i) == '#' || sb.charAt(i) == ',') {
                 sb.deleteCharAt(i);
             } else {
                 break;
             }
         }
         sb.append("}");
         return sb.toString();
    }

    /**
     * This method will be invoked second, the argument data is what exactly
     * you serialized at method "serialize", that means the data is not given by
     * system, it's given by your own serialize method. So the format of data is
     * designed by yourself, and deserialize it here as you serialize it in 
     * "serialize" method.
     */
    public TreeNode deserialize(String data) {
        // write your code here
        //反序列化
        //先将序列化的字符串,取出中间部分,并用“,”分割为字符数组
        //取出第一个字符转换为int,并放入新生成的根节点中
        if (data.equals("{}")) {
            return null;
        }
        //substring(a,b);左闭右开区间[a,b)
        String[] values = data.substring(1, data.length() - 1).split(",");   
        TreeNode root = new TreeNode(Integer.parseInt(values[0]));
        
        //创建队列,并加入root
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        
        //循环字符串数组,如果不是#就转换后,左右依次添加到队首的左右有儿子
        //并加入队列等待添加孙子节点
        boolean isLeftChild = true;
        for (int i = 1; i < values.length; i++) {
            if (!"#".equals(values[i])) {
                TreeNode child = new TreeNode(Integer.parseInt(values[i]));
                if (isLeftChild) {
                    queue.peek().left = child;
                } else {
                    queue.peek().right = child;
                }
                queue.offer(child);
            }
            //走到右节点之后,说明当前节点的左右节点信息已添加完毕
            //将待添加的TreeNode从队列中移除,准备添加下一节点
            if (!isLeftChild) {
                queue.poll();
            }
            //左右节点信息取反
            isLeftChild = !isLeftChild;
        }
        return root;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值