《剑指Offer》Java刷题 NO.61 序列化二叉树(二叉树,序列化(遍历),反序列化(构造),前序、层序遍历)

《剑指Offer》Java刷题 NO.61 序列化二叉树(二叉树,序列化(遍历),反序列化(构造),前序、层序遍历)

传送门:《剑指Offer刷题总目录》

时间:2020-07-16
题目:

请实现两个函数,分别用来序列化和反序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过某种符号表示空节点(#),以 !表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。


思路:考察二叉树的遍历和构造二叉树
大致题意就是,例如对于一颗结点为0-6的满二叉树,先序遍历,序列化之后应该是:

0!1!3!#!#!4!#!#!2!5!#!#!6!#!#!

前中后序遍历、层序遍历都很简单,序列化的话用一个StringBuilder就好了,这个地方复杂的是反序列化,需要维持一个index去取对应位置的value


Java代码:

import java.util.LinkedList;
import java.util.Queue;

/**
 * @author LiMin
 * @Title: SerializeTree
 * @Description: 请实现两个函数,分别用来序列化和反序列化二叉树
 * @date 2020/7/16  15:00
 */
public class SerializeTree {
    public static void main(String[] args) {
        TreeNode node1 = new TreeNode(1);
        TreeNode node2 = new TreeNode(2);
        TreeNode node3 = new TreeNode(3);
        TreeNode node4 = new TreeNode(4);
        TreeNode node5 = new TreeNode(5);
        TreeNode node6 = new TreeNode(6);
        TreeNode node7 = new TreeNode(7);
        node1.left = node2;
        node1.right = node3;
        node2.left = node4;
        node4.right = node5;
        node3.left = node6;
        node5.right = node7;
        SerializeTree serial = new SerializeTree();
        String str = serial.serialBFS(node1);
        TreeNode node0 = serial.deserialBFS(str);
        System.out.println(node0.val);
    }

    /**
     * 前序遍历序列化
     */
    public String serialPreOrder(TreeNode pRoot) {
        if (pRoot == null) {
            return null;
        }
        StringBuilder builder = new StringBuilder();
        preStrBuild(pRoot, builder);
        return builder.toString();
    }

    private void preStrBuild(TreeNode pRoot, StringBuilder builder) {
        if (pRoot == null) {
            builder.append("#!");
            return;
        }
        builder.append(pRoot.val + "!");
        preStrBuild(pRoot.left, builder);
        preStrBuild(pRoot.right, builder);
    }

    /**
     * 前序遍历反序列化
     */
    public TreeNode deserialPreOrder(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        String[] strings = str.split("!");
        return preTreeBuild(strings);
    }

    private int index = 0;

    private TreeNode preTreeBuild(String[] strings) {
        TreeNode root = null;
        if (strings[index].equals("#")) {
            index++;
            return root;//"#"直接将结点返回,没有左右子结点
        }//equal比较字符串内容
        root = new TreeNode(Integer.parseInt(strings[index]));
        index++;//每用掉一个string,index就向前走一步
        root.left = preTreeBuild(strings);
        root.right = preTreeBuild(strings);
        return root;
    }

    /**
     * 层序遍历序列化
     */
    public String serialBFS(TreeNode pRoot) {
        if (pRoot == null) {
            return null;
        }
        StringBuilder builder = new StringBuilder();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(pRoot);
        while (!queue.isEmpty()) {
            //null也放进队列
            TreeNode cur = queue.poll();
            if (cur == null) {
                builder.append("#!");
                continue;
            }
            builder.append(cur.val + "!");
            queue.offer(cur.left);
            queue.offer(cur.right);
        }
        return builder.toString();
    }

    /**
     * 层序遍历反序列化
     */
    public TreeNode deserialBFS(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        String[] strings = str.split("!");
        int idx = 0;
        Queue<TreeNode> queue = new LinkedList<>();
        TreeNode head = new TreeNode(Integer.parseInt(strings[idx++]));
        queue.offer(head);
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            if (!strings[idx].equals("#")) {
                cur.left = new TreeNode(Integer.parseInt(strings[idx++]));
                queue.offer(cur.left);
            } else {
                idx++;//null结点不用再放进队列了,后面没有子树了;cur.left本来就是null
            }
            if (!strings[idx].equals("#")) {
                cur.right = new TreeNode(Integer.parseInt(strings[idx++]));
                queue.offer(cur.right);
            } else {
                idx++;//null结点不用再放进队列了,后面没有子树了;cur.right本来就是null
            }
        }
        return head;
    }
}
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页