7.二叉树的序列化和反序列化

描述

设计一个算法,并编写代码来序列化和反序列化二叉树。将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”。如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列化为一个字符串, 并且可以将字符串反序列化为原来的树结构。

注意事项

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时,你可以作为输入调试你的代码。你可以采用其他的方法进行序列化和反序列化。

关键点

  1. 要知道序列化是什么
    //www.greatytc.com/writer#/notebooks/15589466/notes/16028033/preview
  2. 无论是序列化还是反序列化都需要用queue来控制结点的执行顺序,当然queue的实现要根据题目需求选择是用LinkedList()方法还是ArrayList方法,本题算法中用到大量读取操作,若用LinkedList来实现queue不方便,本题用了ArrayList来实现queue

代码

/**
 * 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;
 *     }
 * }
 */
class Solution {            
    // 加public表示全局类,该类可以import到任何类内
    // 不加public默认为保留类,只能被同一个包内的其他类引用

    /**
     * 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) {
        if (root == null) {
            return "{}";
        }
        
        /* 利用for循环将树中结点全部添加到队列里面,利用队列来控制序列化顺序
         * queue不是一个队列,是一个数组只是名字是queue
         */
        ArrayList<TreeNode> queue = new ArrayList<TreeNode>();
        
        queue.add(root);
        for (int i = 0; i < queue.size(); i++) {
            // queue是动态数组用get()方法来得到下标对应的数值
            TreeNode node = queue.get(i);
            
            // 空结点跳过不执行叶子结点添加的操作
            if (node == null) {         
                continue;
            }
            // 无需理会叶子结点是不是空,把当前非空结点的叶子结点添加到了队列中
            queue.add(node.left);                 
            queue.add(node.right);
        }

        // 去掉队列结尾的空结点
        while (queue.get(queue.size() - 1) == null) {
            queue.remove(queue.size() - 1);
        }

        // 根据队列往动态数组里添加相应的值
        // StringBuilder对象是动态对象,允许扩充它所封装的字符串中字符的数量
        StringBuilder sb = new StringBuilder();   
        sb.append("{");
        sb.append(queue.get(0).val);
        // 在for循环前已经将初值加入sb中,所以 i 初值应设为1
        for (int i = 1; i < queue.size(); i++) {
            if (queue.get(i) == null) {
                sb.append(",#"); 
            } 
            else { 
                sb.append(",");
                sb.append(queue.get(i).val);
            }
        }
        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) {
        // 字符用equals,数值用==
        if (data.equals("{}")) {    
            return null;
        }

        // 此处需注意用点截取data的区间
        // 字符串长度用length()
        String[] vals = data.substring(1, data.length() - 1).split(",");
        ArrayList<TreeNode> queue = new ArrayList<TreeNode>();
        TreeNode root = new TreeNode(Integer.parseInt(vals[0]));   
        /* 新建一节点,节点值为vals[0]
         * Integer.parseInt()将字符串转化为整型
         */

        queue.add(root);
        boolean isLeftChild = true;
        // index是queue的索引
        int index = 0;
        // i 是vals的索引
        for (int i = 1; i < vals.length; i++) {   
        // 数组长度用length
            // 此处同样要注意先判断是不是空结点再讨论结点的子结点
            if (!vals[i].equals("#")) {
                TreeNode node = new TreeNode(Integer.parseInt(vals[i]));
                if (isLeftChild) {
                // 注意此处index=0,i=1
                    queue.get(index).left = node;    
                }
                else {
                    queue.get(index).right = node;  
                }
                queue.add(node);              
                /* '#'所的代表的空指针不要加入queue,没有任何意义,
                 * 此时for循环遍历的是index,即node的父节点,
                 * for循环接下来还要遍历node来确定node的子节点
                 * 此处不能忘记将node加入queue
                 */
            }
            if (!isLeftChild) {
                index++;     
                /* isLeftChild=false时说明此时index对应的结点的右儿子已经添加到队列中了,
                 * 应将index往后移一位 
                 */              
            }
            // i 每变化一次 isLeftChild 进行一次变化
            isLeftChild = !isLeftChild;
        }

        return root;
    } 
}

错误

  1. 单引号里面放一个字符,双引号里放多个字符
错误
错误代码
正确代码

需要先判断node是否为空,若node都为空研究node左右子结点无意义

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容