2018-06-16 18:53:36

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

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

1、以某种存储形式使自定义对象持久化;
2、将对象从一个地方传递到另一个地方。
3、使程序更具维护性。
本篇文章主要讨论的是二叉树的序列化和反序列化,分别讨论了普通二叉树和二叉搜索树的情况。
一、普通二叉树的序列化和反序列化
问题描述:
问题求解:
序列化和反序列化二叉树本质上其实是问如何将二叉树描述成字符串形式,如何从字符串中提取并重建二叉树。和以往建立二叉树是一样的,如果我们通过前序遍历的方式对二叉树所有节点进行表示,那么在重建二叉树的时候,就可以完全按照前序遍历的方式进行重建。问题在于,如何对数据进行表示,由于各个数的位数不同,所以一般来说会使用空格作为分隔符,同时采用"#“来表示空节点。
但是这样的序列化方式显然是比较浪费空间的,如果单纯的使用其10进制的表示,对于十几亿的数字,单纯将其转化成字符串,那么就会有11个char,占用的字节数可以会达到11个字节,这样对空间和效率都会产生不利的影响。那么如果提高空间的利用率呢?因为一个整形数本身是由4个字节来表示的,我们可以对每8位做一次转化,将之转成char,这样就可以用4个字节来表示一个整数。
事实上,下面的解法就是使用上述的思路,使用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;}
}

精简版:

public class Codec {// 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 sb) {if (root == null) sb.append("00000");else {int val = root.val;sb.append('1').append((char) (val >> 24)).append((char) ((val >> 16) & (0x00ff))).append((char) ((val >> 8) & (0x0000ff))).append((char) (val & (0x000000ff)));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[1]);}private TreeNode helper(char[] chs, int[] pos) {if (pos[0] >= chs.length) return null;if (chs[pos[0]] == '0') {pos[0] += 5;return null;}int val = chs[pos[0] + 1] << 24 | chs[pos[0] + 2] << 16 | chs[pos[0] + 3] << 8 | chs[pos[0] + 4];TreeNode root = new TreeNode(val);pos[0] += 5;root.left = helper(chs, pos);root.right = helper(chs, 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) {returnbytes[0] & (0xff000000) |bytes[1] & (0x00ff0000) |bytes[2] & (0x0000ff00) |bytes[3] & (0x000000ff);}
}

转载于:https://www.cnblogs.com/TIMHY/p/9191122.html

序列化与反序列化二叉树相关推荐

  1. 序列化以及反序列化二叉树

    有些问题需要把二叉树序列化,可用于传输或者保存等,当然,有些题目也需要你去序列化以及反序列化,你懂的! 二叉树的定义如下: package com.hbut.bean;public class Tre ...

  2. c语言二叉树反序列化,序列化和反序列化二叉树

    题目描述 请实现两个函数,分别用来序列化和反序列化二叉树 /* public class TreeNode { int val = 0; TreeNode left = null; TreeNode ...

  3. 序列化和反序列化二叉树 -----前序,中序,后序,层序

    目录 一.序列化和反序列化 1.什么是序列化和反序列化 二.前序遍历 1.序列化 1.问题分析 2.代码实现 2.反序列化 1.问题分析 2.代码实现 三.后序遍历 1.序列化 1.思路分析 2.代码 ...

  4. python代码实现二叉树的序列化和反序列化

    python代码实现二叉树的序列化和反序列化 二叉树的序列化 二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字 符串,从而使得内存中建立起来的二叉树可以持久保存. 二叉树的反序 ...

  5. 二叉树序列化与反序列化相关题目(Leetcode题解-Python语言)

    297. 二叉树的序列化与反序列化(剑指 Offer 37. 序列化二叉树)(剑指 Offer II 048. 序列化与反序列化二叉树) class Codec:def serialize(self, ...

  6. LeetCode——二叉树序列化与反序列化

    文章目录 题目 思路 问题一 问题二 代码实现 题目 请实现两个函数,分别用来序列化和反序列化二叉树. 设计一个算法来实现二叉树的序列化与反序列化.不限定序列 / 反序列化算法执行逻辑,你只需要保证一 ...

  7. lintcode 7. 二叉树的序列化和反序列化 Python代码

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

  8. java二叉树的序列化_二叉树的序列化和反序列化

    import java.util.LinkedList; import java.util.Queue; /** * 序列化和反序列化二叉树 * 先序.后序 * (中序不能实现) * 按层 */ pu ...

  9. C++之二叉树的序列化与反序列化

    问题 来源: LintCode7 设计一个算法,并编写代码来序列化和反序列化二叉树.将树写入一个文件被称为"序列化",读取文件后重建同样的二叉树被称为"反序列化" ...

  10. 剑指offer:二叉树序列化与反序列化 - Python

    转载自:https://blog.csdn.net/u010005281/article/details/79787278 题目描述 请实现两个函数,分别用来序列化和反序列化二叉树. 解题思路 序列化 ...

最新文章

  1. 前端部分面试题整理,欢迎补充
  2. Python解决NameError: name ‘reload‘ is not defined的问题
  3. 一个关于使用 $month,$dayOfMonth 进行按月/日统计的问题
  4. 如何用xapmm测试php_如何在Xampp中运行PHP程序?
  5. php+当前+日期+函数是,php时间日期的处理函数
  6. 输入一颗二元树,从上向下按层打印树的每个节点,同一层中,按照从左到右的顺序打印。...
  7. java工程师面试题:如何判断链表有环?
  8. 大坑:用SQLyog连mysql的部分操作不能同步到从库
  9. ADO.NET 对象模型
  10. linux man中文手册
  11. 第四天:使用 session cookie redis完善登录验证及登录路由
  12. Visual Studio 2008操作技巧
  13. 两台usrp实现收发_选购光纤收发器时应该注意哪些事项?
  14. Android 百度地图SDK与导航SDK相关问题
  15. Codeforces 918D - MADMAX
  16. MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)
  17. kvm最多能管几台服务器,高效管理500台服务器的kvm切换器配置方案
  18. parameter缩略语_WB 术语及缩略语表
  19. duilib学习------网易云信图片中间加文字
  20. 绝世舞姬计算机弹音乐,绝世舞姬(伴奏)

热门文章

  1. centos7.4批量自动化安装(pxe、cobbler、制作自动化iso镜像);pxe安装;cobbler安装;
  2. NYOJ --277 车牌号
  3. 04_Java基础语法_第4天(数组)
  4. 深层网络搜索核心技术研讨
  5. [Erlang 0041] 详解io:format
  6. router阻止telnet自身的两种方法
  7. 如何解决安装CentOS时遇到引导分区位于一个GPT分区方案的错误提示问题
  8. Android进程与线程基本知识
  9. 11款实用的一句话网站设计代码
  10. 先序、中序和后序数组两两结合重构二叉树 -- 图解