数据结构与算法 - 二叉树的序列化与反序列化

首先说下什么是序列化、持久化。

其实就是写入到文件中,这样下次便于读取再次修改啥的。
那么那些牛客什么的OJ网站是怎么判断我们写的代码输出的树的结构是否正确呢?他们其实就是利用了树的序列化,把树的这种结构转换为字符串,这样的话就可以方便比较。我们不能直接拿节点的内存地址来存储把,所以我们需要建立一套规则,使得二叉树可以与字符串一一对应,根据一个二叉树可以唯一的得到一个字符串,根据一个字符串也可以唯一的还原出一棵二叉树。
序列化需要将每个结点按照一定的顺序转换为字符串,关键是这个顺序是什么顺序,这个顺序其实就是遍历树的顺序,按照遍历结点的顺序将结点转化为字符串即可,因此先序遍历、中序遍历、后序遍历、按层遍历都可以进行序列化。
这里我写了中序与层序遍历的序列化作为参考:
- “#”代表的是空节点 "!"代表了结尾

  • 首先是节点的定义:
public static class Node{
        public int value;
        public Node left;
        public Node right;
        public Node(int value){
            this.value = value;
        }
    }
  • 中序遍历实现序列化:
//二叉树的序列化,按照先序的顺序,其实就是把二叉树转换成一个字符串
    public static String serialByPre(Node head){
        if(head == null){
            return "#!";
        }
        String res = head.value + "!";
        res += serialByPre(head.left);
        res += serialByPre(head.right);
        return res;
    }
    // 二叉树的反序列化
    public static Node reconByPreString(String preStr){
        String[] values = preStr.split("!");
        Queue<String> queue = new LinkedList<>();
        for (int i = 0; i < values.length; i++) {
            queue.add(values[i]);
        }
        return reconPreOrder(queue);
    }

    //一个递归函数 恢复二叉树的结构
    public static Node reconPreOrder(Queue<String> queue){
        String cur = queue.poll();
        if(cur.equals("#")){
            return null;
        }

        Node head = new Node(Integer.valueOf(cur));
        head.left = reconPreOrder(queue);
        head.right = reconPreOrder(queue);
        return head;
    }
  • 层序遍历实现序列化:
 //序列化一个二叉树,使用层序遍历方式
    public static String serialByLevel(Node head){
        if(head == null){
            return "#!";
        }
        String res = head.value + "!";
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        while (!queue.isEmpty()){
            Node cur = queue.poll();
            if(cur.left != null){
                res += cur.left.value + "!";
                queue.offer(cur.left);
            }else {
                res += "#!";
            }

            if(cur.right != null){
                res += cur.right.value + "!";
                queue.offer(cur.right);
            }else{
                res += "#!";
            }
        }
        return res;
    }

    //非递归恢复二叉树的主函数
    public static Node reconByLevelString(String levelStr){
        String[] values = levelStr.split("!");
        int index = 0;
        Node head = generateNodeByString(values[index++]);
        Queue<Node> queue = new LinkedList<>();
        if(head != null){
            queue.offer(head);
        }
        Node node = null;
        while (!queue.isEmpty()){
            node = queue.poll();
            node.left = generateNodeByString(values[index++]);
            node.right = generateNodeByString(values[index++]);
            if(node.left != null){
                queue.offer(node.left);
            }
            if(node.right != null){
                queue.offer(node.right);
            }
        }
        return head;
    }


    public static Node generateNodeByString (String val){
        if(val.equals("#")){
            return null;
        }
        return new Node(Integer.valueOf(val));
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值