2

二叉树的序列化和反序列化 - Grey Zeng

 1 year ago
source link: https://www.cnblogs.com/greyzeng/p/16789819.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

作者:Grey

原文地址:

博客园:二叉树的序列化和反序列化

CSDN:二叉树的序列化和反序列化

题目链接见:LeetCode 297. Serialize and Deserialize Binary Tree

可以用如下三种方式

第一种方式,先序遍历生成序列化字符串,然后按先序规则再反序列化;

第二种方式,后序遍历生成序列化字符串,然后按后序规则再反序列化;

第三种方式,按层遍历生成序列化字符串,然后按层次规则再反序列化。

注:这里不能用中序方式序列化和反序列化,因为,如果二叉树是如下两棵

image

image

两棵树的中序遍历结果都是[null,a,a,a,null],这样进行反序列化的时候,就无法区分这两棵树了。

其次,针对任何一棵二叉树,我们需要将一些空的节点补充完整,比如下述二叉树

image

其中 b 的左孩子,c 的左孩子,d 的右孩子,都是空节点,我们可以用 null 来表示,但是不能忽略,所以以按层序列化为例,我们将空节点设置为‘#’字符,并用'[]'框住序列化的字符串,然后用逗号分隔节点,所以,上述二叉树

按层序列化的结果是[a,b,c,#,d,#,e,f,#]

// 二叉树按层遍历经典实现。
    public static String serialize(TreeNode head) {
        if (head == null) {
            return "[]";
        }
        StringBuilder sb = new StringBuilder("[");
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(head);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            sb.append(node == null ? "#" : String.valueOf(node.val)).append(",");
            if (node != null) {
                queue.offer(node.left);
                queue.offer(node.right);
            }
        }
        sb.append("]");
        return sb.toString();
    }

反序列化的方式就是把上述字符串还原成一个二叉树,使用一个队列即可,代码如下:

    // 按层反序列化
    public static TreeNode deserialize(String data) {
        if ("[]".equals(data)) {
            return null;
        }
        data = data.substring(1, data.length() - 2);
        String[] values = data.split(",");
        TreeNode head = new TreeNode(Integer.valueOf(values[0]));
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(head);
        int size = 1;
        while (!queue.isEmpty() && size < values.length) {
            TreeNode c = queue.poll();
            c.left = "#".equals(values[size]) ? null : new TreeNode(Integer.valueOf(values[size]));
            size++;
            if (size < values.length) {
                c.right = "#".equals(values[size]) ? null : new TreeNode(Integer.valueOf(values[size]));
                size++;
            }
            if (c.left != null) {
                queue.offer(c.left);
            }
            if (c.right != null) {
                queue.offer(c.right);
            }
        }
        return head;
    }

先序序列化/反序列化,后序序列化/反序列化方法类似

// 后序方式序列化 迭代方法
    public static String serialize3(TreeNode head) {
        if (head == null) {
            return "[]";
        }
        // 后序遍历的结果加入栈(可以用递归也可以用迭代)
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();
        stack1.push(head);
        while (!stack1.isEmpty()) {
            TreeNode c = stack1.pop();
            stack2.push(c);
            if (c != null) {
                stack1.push(c.left);
                stack1.push(c.right);
            }
        }
        // 栈->字符串
        StringBuilder sb = new StringBuilder("[");
        while (!stack2.isEmpty()) {
            TreeNode node = stack2.pop();
            sb.append(node == null ? "#" : node.val).append(",");
        }
        sb.append("]");
        return sb.toString();
    }

    // 后序方式反序列化 迭代方式
    public static TreeNode deserialize3(String data) {
        if ("[]".equals(data)) {
            return null;
        }
        String[] values = data.substring(1, data.length() - 2).split(",");
        Stack<String> stack = new Stack<>();
        for (String value : values) {
            stack.push(value);
        }
        return posDerial(stack);
    }

    private static TreeNode posDerial(Stack<String> stack) {
        String s = stack.pop();
        if ("#".equals(s)) {
            return null;
        }
        TreeNode root = new TreeNode(Integer.valueOf(s));
        root.right = posDerial(stack);
        root.left = posDerial(stack);
        return root;
    }

    // 先序方式序列化 迭代做法
    // 头 左 右
    public static String serialize2(TreeNode head) {
        if (head == null) {
            return "[]";
        }
        StringBuilder sb = new StringBuilder("[");
        Stack<TreeNode> queue = new Stack<>();
        queue.push(head);
        while (!queue.isEmpty()) {
            TreeNode c = queue.pop();
            sb.append(c == null ? "#" : c.val).append(",");
            if (c != null) {
                queue.push(c.right);
                queue.push(c.left);
            }
        }
        sb.append("]");
        return sb.toString();
    }

    // 先序反序列化
    public static TreeNode deserialize2(String data) {
        if ("[]".equals(data)) {
            return null;
        }
        String[] values = data.substring(1, data.length() - 2).split(",");
        Queue<TreeNode> queue = new LinkedList<>();
        for (String value : values) {
            queue.offer("#".equals(value) ? null : new TreeNode(Integer.valueOf(value)));
        }
        return preDesrial(queue);
    }

    private static TreeNode preDesrial(Queue<TreeNode> queue) {
        TreeNode node = queue.poll();
        if (node == null) {
            return null;
        }
        node.left = preDesrial(queue);
        node.right = preDesrial(queue);
        return node;
    }

更多#

算法和数据结构笔记


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK