序列化与反序列化二叉树

2018-06-16 18:53:36

序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。反序列化顾名思义就是通过信息流对对象进行重建的过程。

一般来说序列化和反序列化有如下的作用:

1、以某种存储形式使自定义对象持久化;

2、将对象从一个地方传递到另一个地方。

3、使程序更具维护性。

本篇文章主要讨论的是二叉树的序列化和反序列化,分别讨论了普通二叉树和二叉搜索树的情况。

一、普通二叉树的序列化和反序列化

问题描述:

问题求解:

序列化和反序列化二叉树本质上其实是问如何将二叉树描述成字符串形式,如何从字符串中提取并重建二叉树。和以往建立二叉树是一样的,如果我们通过前序遍历的方式对二叉树所有节点进行表示,那么在重建二叉树的时候,就可以完全按照前序遍历的方式进行重建。问题在于,如何对数据进行表示,由于各个数的位数不同,所以一般来说会使用空格作为分隔符,同时采用"#“来表示空节点。但是这样的序列化方式显然是比较浪费空间的,因为一个整形数本身是由4个字节来表示的,如果单纯的使用其10进制的表示那么占用的字节数又可以会达到11个,这样对空间和效率都会产生不利的影响。

事实上,我们完全可以使用4个字节来表示一个整形数,同时可以再加上一个字节来表示是否为空节点,这样对空间的占用就会小很多,另外,由于归一化了长度,即所有数据的长度都为5个字节,那么就不需要使用空格来作为分隔符了,这样又进一步减少了空间的开销,因此,采用这种方法来序列化和反序列化二叉树是比较可取的。

public class SerializeandDeserializeTree {
    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        StringBuffer sb = new StringBuffer();
        preOrder(root, sb);
        return sb.toString();
    }

    private void preOrder(TreeNode root, StringBuffer stringBuffer) {
        if (root == null) {
            stringBuffer.append("00000");
        }
        else {
            byte[] bytes = intToByte(root.val);
            stringBuffer.append(‘1‘).append((char) bytes[0]).append((char) bytes[1]).append((char) bytes[2]).append((char) bytes[3]);
            preOrder(root.left, stringBuffer);
            preOrder(root.right, stringBuffer);
        }
    }

    private byte[] intToByte(int val) {
        return new byte[]{
                (byte) (val >> 24),
                (byte) (val >> 16),
                (byte) (val >> 8),
                (byte) val
        };
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        return helper(data.toCharArray(), new int[]{0});
    }

    private TreeNode helper(char[] data, int[] pos) {
        if (pos[0] >= data.length) return null;
        if (data[pos[0]] == ‘0‘) {
            pos[0] += 5;
            return null;
        }
        int val =
                (data[pos[0] + 1]) << 24 & 0xff000000 |
                (data[pos[0] + 2]) << 16 & 0x00ff0000 |
                (data[pos[0] + 3]) << 8 & 0x0000ff00 |
                (data[pos[0] + 4]) << 0 & 0x000000ff;
        pos[0] += 5;
        TreeNode root = new TreeNode(val);
        root.left = helper(data, pos);
        root.right = helper(data, pos);
        return root;
    }
}

二、 二叉搜索树的序列化和反序列化

问题描述:

问题求解:

二叉搜索树是二叉树的特例,当然是可以使用上面的思路直接AC的,但是本题中特别要求了,序列化的字符串要尽可能的紧凑,考虑到二叉搜索树的性质,我们可以进一步的简化序列化的长度。正如上面提到的,对于整形数使用4个字节表示可以大大简化存储数量,这个是毋庸置疑的,只是在二叉搜索树中,我们不再需要额外存储空节点信息,因为对于二叉搜索树来说,其性质是左子树所有节点都要比根节点小,右子树所有节点都要比根节点大,因此我们可以利用这个性质来判断当前流数据是否为此根节点的子树。

综上所述,我们需要维护一下每个根节点左右子树的大小范围以判断当前的流数据是否应该挂在当前根节点下,如果不在范围内,直接返回空值即可。因而,对于整个前序遍历的序列化字符串来说,我们只需要4个字节来表述整形数即可。

public class SerializeandDeserializeBST {
    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        StringBuffer sb = new StringBuffer();
        preOrder(root, sb);
        return sb.toString();
    }

    byte[] intToByte(int val) {
        return new byte[]{
                (byte)(val >> 24),
                (byte)(val >> 16),
                (byte)(val >> 8),
                (byte)val
        };
    }

    void preOrder(TreeNode root, StringBuffer sb) {
        if (root != null) {
            byte[] tmp = intToByte(root.val);
            sb.append((char) tmp[0]).append((char) tmp[1]).append((char) tmp[2]).append((char) tmp[3]);
            preOrder(root.left, sb);
            preOrder(root.right, sb);
        }
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        return helper(data.toCharArray(), new int[]{0}, Integer.MIN_VALUE, Integer.MAX_VALUE);
    }

    private TreeNode helper(char[] data, int[] pos, int low, int high) {
        if(pos[0] >= data.length) return null;
        int val =
                data[pos[0] + 0] << 24 & (0xff000000) |
                data[pos[0] + 1] << 16 & (0x00ff0000) |
                data[pos[0] + 2] << 8 & (0x0000ff00) |
                data[pos[0] + 3] << 0 & (0x000000ff);
        if(val < low || val > high) return null;
        TreeNode root = new TreeNode(val);
        pos[0] += 4;
        root.left = helper(data, pos, low, val);
        root.right = helper(data, pos, val, high);
        return root;
    }

    int byteToInt(byte[] bytes) {
        return
                bytes[0] & (0xff000000) |
                bytes[1] & (0x00ff0000) |
                bytes[2] & (0x0000ff00) |
                bytes[3] & (0x000000ff);
    }
}

原文地址:https://www.cnblogs.com/TIMHY/p/9191122.html

时间: 2024-09-30 21:11:06

序列化与反序列化二叉树的相关文章

序列化和反序列化二叉树

今天练习算法,在leetcode上做了一道练习,照着上面的分析写了下面的代码,编译执行也都没有问题,在这里写写. 这里采用二叉树的先序遍历方式作为序列化和反序列化的主要思路,对空的子树用'#'进行记录. 在序列化的时候,使用递归进行先序遍历,递归执行到空节点,则保存'#'并返回:否则记录当前节点的值,并继续对其左右节点进行遍历. 同样,在反序列化的时候,当前读到的值作为新子树的根节点root,下一个读到的节点则为root节点的左子树root->left,并将当前索引值的引用传入下一步的递归,直到

[leetcode]297. Serialize and Deserialize Binary Tree 序列化与反序列化二叉树

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another comput

请实现两个函数,分别用来序列化和反序列化二叉树

import java.util.LinkedList; import java.util.Queue; public class Solution { String Serialize(TreeNode root) { StringBuilder sb = new StringBuilder(); if(root==null) { sb.append("#,"); return sb.toString(); } sb.append(String.valueOf(root.val));

lintcode 中等题:binary tree serialization 二叉树的序列化和反序列化

题目 二叉树的序列化和反序列化 设计一个算法,并编写代码来序列化和反序列化二叉树.将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”. 如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列化为一个字符串,并且可以将字符串反序列化为原来的树结构. 样例 给出一个测试数据样例, 二叉树{3,9,20,#,#,15,7},表示如下的树结构: 3 / 9 20 / 15 7 我们的数据是进行BFS遍历得到的.当你测试结果wrong answer时,你可以作为输

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

设计一个算法,并编写代码来序列化和反序列化二叉树.将树写入一个文件被称为"序列化",读取文件后重建同样的二叉树被称为"反序列化". 如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列化为一个字符串,并且可以将字符串反序列化为原来的树结构. 注意事项 There is no limit of how you deserialize or serialize a binary tree, LintCode will take your output o

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

http://blog.csdn.net/qq_27703417/article/details/70958692 先序遍历二叉树,如果遇到空节点,就在str的末尾加上"#!","#"表示这个节点为空,节点值不存在,当然你也可以用其他的特殊字符,"!"表示一个值的结束.如果遇到不为空的节点,假设节点值为3,就在str的末尾加上"3!".现在请你实现树的先序序列化. 先序遍历 import java.util.*; //使用递归

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

一个二叉树被序列化为数组,如何反序列化,也就是如何从序列化好的一个数组恢复成二叉树? 在上一篇文章中讲述了如何将一个有序数组创建成一个二叉搜索树,那么如果将将一个儿茶搜索树序列化为一个有序数组,然后按照上面的方法在反序列化即可.对二叉搜索树进行中序遍历即可得到一个有序的数组,那么上篇文章已经完成了对二叉搜索树的序列化和反序列化.同时如果想将二叉搜索树的序列化和反序列化的结果通过文件读取,也是同样的道理. 设计一个算法,将一棵二叉搜索树(Binary Search Tree,BST)保存到文件中,

Leetcode 297.二叉树的序列化和反序列化

二叉树地序列化和反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据. 请设计一个算法来实现二叉树的序列化与反序列化.这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构. 示例:  你可以将以下二叉树: 序列化为 "[1,2,3,null,null,4,5]" 提示: 这与 Le

二叉树的序列化和反序列化(先序,按层序列化),包含递归图

目录 二叉树的序列化与反序列化 按层序列化 使用#!和!的原因: 二叉树的序列化与反序列化 序列化:将对象的状态信息转换为可以存储或传输的形式的过程 二叉树的序列化:就是将二叉树转换成字符串 二叉树的反序列化:通过字符串还原一棵二叉树,返回树的头节点. 先序序列化二叉树 上面这棵树的先序序列化结果为5!3!2!1!#!#!#!4!#!#!8!7!6!#!#!#!10!9!#!#!11!#!#! 从上图中我们可以看出在节点为空的位置使用"#!"来代替,每个节点后的数值都添加一个"