• 前序、后序及层次遍历实现二叉树的序列化与反序列化


    文章目录


    本文将实现两个方法,一个是序列化方法,定义如下,

    public String serialize(TreeNode root) {}
    
    • 1

    语义:传入一颗二叉树,以字符串的形式返回它的序列化结果。

    另一个是反序列化方法,定义如下,

    public TreeNode deserialize(String data) {}
    
    • 1

    语义:传入之前的序列化结果,还原出这颗二叉树。

    树节点定义如下,

    class TreeNode {
         int val;
         TreeNode left;
         TreeNode right;
         TreeNode(int x) { val = x; }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    下面分别使用二叉树树的前序遍历、后续遍历以及层次遍历进行序列化与反序列化。

    二叉树的各种遍历方式及其递归与非递归的实现可参考这篇文章:
    https://blog.csdn.net/weixin_45685353/article/details/106694041

    前序

    序列化方法需额外引入一个实现二叉树前序遍历的方法,其整体实现如下,

    	public String serialize(TreeNode root) {
            StringBuilder sb = new StringBuilder();
            pre(root, sb);
            return sb.toString();
        }
        private void pre(TreeNode root, StringBuilder sb) {
            if (root == null) {
                sb.append("#,");
                return;
            }
            sb.append(root.val).append(",");
            pre(root.left, sb);
            pre(root.right, sb);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    其反序列化方法也许借助额外的方法,因为序列化的结果形如[根节点,左节点,右节点],因此,反序列化的时候也是按照这个顺序重构就好,实现如下,

    	int i;// 全局变量,表示数组下标
        public TreeNode deserialize(String data) {
            i = 0;// 从头开始
            return pre(data.split(","));
        }
        
        private TreeNode pre(String[] s) {
            if ("#".equals(s[i])) {
                return null;
            }
            TreeNode root = new TreeNode(Integer.parseInt(s[i]));
            i++;
            root.left = pre(s);
            i++;
            root.right = pre(s);
            return root;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    后序

    后序遍历的序列化实现跟前序遍历差不多,改变下位置即可,如下,

    	public String serialize(TreeNode root) {
            StringBuilder sb = new StringBuilder();
            post(root, sb);
            return sb.toString();
        }
    
        private void post(TreeNode root, StringBuilder sb) {
            if (root == null) {
                sb.append("#,");
                return;
            }
            post(root.left, sb);
            post(root.right, sb);
            sb.append(root.val).append(",");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    其反序列化也差不多,因为其序列化结果形如[左节点,右节点,根节点],因此我们在反序列化的时候,从尾部开始,即先构造根节点,再构造右节点,最后左节点,代码如下,

    	int i;// 全局变量,表示数组下标
    	public TreeNode deserialize(String data) {
            String[] s = data.split(",");
            i = s.length - 1;// 从尾部开始
            return post(s);
        }
    
        private TreeNode post(String[] s) {
            if ("#".equals(s[i])) {
                return null;
            }
            TreeNode root = new TreeNode(Integer.parseInt(s[i]));
            i--;
            root.right = post(s);
            i--;
            root.left = post(s);
            return root;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    层次

    借助队列这种数据结构,实现对二叉树的层次遍历,空节点用’#‘表示,用’,'作为分隔符,其序列化方法的实现如下,

    public String serialize(TreeNode root) {
            StringBuilder sb = new StringBuilder();
            LinkedList<TreeNode> queue = new LinkedList<>();
            queue.addLast(root);
            while (!queue.isEmpty()) {
                root = queue.removeFirst();
                if (root == null) {
                    sb.append("#");
                } else {
                    sb.append(root.val);
                    queue.addLast(root.left);
                    queue.addLast(root.right);
                }
                sb.append(",");
            }
            return sb.toString();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    其反序列化方法的实现如下,

    public TreeNode deserialize(String data) {
            String[] s = data.split(",");
            if ("#".equals(s[0])) return null;
            TreeNode root = new TreeNode(Integer.parseInt(s[0])), p = root;
            int i = 1;
            LinkedList<TreeNode> queue = new LinkedList<>();
            queue.addLast(p);
            while (i < s.length) {
                p = queue.removeFirst();
                if (!"#".equals(s[i])) {
                    p.left = new TreeNode(Integer.parseInt(s[i]));
                    queue.addLast(p.left);
                }
                if (i + 1 < s.length && !"#".equals(s[i + 1])) {
                    p.right = new TreeNode(Integer.parseInt(s[i + 1]));
                    queue.addLast(p.right);
                }
                i += 2;
            }
            return root;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    看完本篇文章,随便可以把力扣的这道题给AC了:二叉树的序列化与反序列化

  • 相关阅读:
    前端拿到url地址拼接的参数
    Springboot+vue的财务管理系统(有报告),Javaee项目,springboot vue前后端分离项目。
    UML之类图
    使用perming加速训练可预测的模型
    pandas高效读取大文件的探索之路
    PowerBI依据字段取一列从小到大的第三个值(没三个值取第二个,第二个没有取第一个)
    Linux应急响应笔记
    C++——友元(友元函数、友元类的特点)
    RSA非对称加密算法中的密钥对生成与传输
    6 个最佳 Windows 免费磁盘分区管理器
  • 原文地址:https://blog.csdn.net/weixin_45685353/article/details/126081295