序列化/反序列化二叉树,代码是自己写的

转载 2018年04月14日 23:37:11

题目

设计一个算法能够实现序列化和反序列化一棵二叉树(注意,不是二叉搜索树BST)。这里的序列化指的是将一棵二叉树保存到文件中,反序列化就是从文件中读取二叉树结点值重构原来的二叉树。


思路

前一篇文章保存二叉搜索树到文件中  解决了保存一棵二叉搜索树到文件中的问题,但是由于本题目的意思是要把一棵二叉树保存到文件中并从文件中读出重构二叉树。因为二叉树不一定是二叉搜索树,所以前面文章中的方法不能凑效。


解法

因为二叉树与二叉搜索树的性质不同,所以不能简单的采用前面文章中的方法。不过,我们可以采用先序遍历的思想,只是在这里需要改动。为了能够在重构二叉树时结点能够插入到正确的位置,在使用先序遍历保存二叉树到文件中的时候需要把NULL结点也保存起来(可以使用特殊符号如“#”来标识NULL结点)。

假定二叉树如下所示:

    _30_
   /    \   
  10    20
 /     /  \
50    45  35

则使用先序遍历,保存到文件中的内容如下:

30 10 50 # # # 20 45 # # 35 # #

序列化二叉树

先序遍历的代码可以完成序列化二叉树的工作,不管你信不信,反正我是信了。代码如下:

[cpp] view plain copy
  1. void writeBinaryTree(BinaryTree *p, ostream &out)  //BinaryTree是二叉树结构体,typedef struct node BinaryTree.  
  2. {  
  3.   if (!p) {  
  4.     out << "# ";  
  5.   } else {  
  6.     out << p->data << " ";  
  7.     writeBinaryTree(p->left, out);  
  8.     writeBinaryTree(p->right, out);  
  9.   }  
  10. }  

反序列化二叉树

从文件中读取二叉树结点并重构的方法与前面相似。采用先序遍历的思想每次读取一个结点,如果读取到NULL结点的标识符号“#”,则忽略它。如果读取到结点数值,则插入到当前结点,然后遍历左孩子和右孩子。

[cpp] view plain copy
  1. void readBinaryTree(BinaryTree *&p, ifstream &fin)   
  2. {  
  3.   int token;  
  4.   bool isNumber;  
  5.   if (!readNextToken(token, fin, isNumber)) //readNextToken读取文件下一个值,如果是数字返回true,否则返回false  
  6.     return;  
  7.   if (isNumber) {  
  8.     p = newNode(token);         //newNode函数创建新结点,设定data为token,left和right初始化为NULL  
  9.     readBinaryTree(p->left, fin);  
  10.     readBinaryTree(p->right, fin);  
  11.   }  
  12. }  

进一步思考

除了先序遍历,其实还可以使用层序遍历来序列化二叉树。此外,本文采用先序遍历保存NULL结点的方法存在缺陷,因为这样二叉树结点不能保存标识符。如本方法中二叉树结点值就不能是“#”。如果要能保存各种字符,则需要采用其他方法来实现了。不管怎样,对于面试来讲,这样的解法已经可以过关了。


英文原文:http://www.leetcode.com/2010/09/serializationdeserialization-of-binary.html



我的代码


public class Treeserial {
    public void toSerial(SearchNode node, StringBuffer sb) {
        if (node == null) {
            sb.append("#-");
            return;
        }
        sb.append(node.getKey()).append("-");
        toSerial(node.getLeftChild(), sb);
        toSerial(node.getRightChild(), sb);
        return;
    }

    public void toTree(SearchNode parentNode, Queue<String> queue) {
        if (queue.isEmpty()) {
            return;
        }
        String str = queue.poll();
        //30-10-50-#-#-#-20-45-#-#-35-#-#-";
        if (!"#".equals(str)) {
            SearchNode left = new SearchNode(Integer.parseInt(str), str);
            parentNode.setLeftChild(left);
            toTree(left, queue);
            if (queue.isEmpty()) {
                return;
            }
            str = queue.poll();
            if ("#".equals(str)) {
                return;
            } else {
                SearchNode right = new SearchNode(Integer.parseInt(str), str);
                parentNode.setRightChild(right);
                toTree(right, queue);
            }
        } else {
            if (queue.isEmpty()) {
                return;
            }
            str = queue.poll();
            if ("#".equals(str)) {
                return;
            } else {
                SearchNode right = new SearchNode(Integer.parseInt(str), str);
                parentNode.setRightChild(right);
                toTree(parentNode, queue);
            }
        }
    }

    public static void main(String[] args) {
        Treeserial t = new Treeserial();
        /* SearchNode root = new SearchNode(30,"30");
        root.setLeftChild(new SearchNode(10,"10"));
        root.setRightChild(new SearchNode(20,"20"));
        root.getLeftChild().setLeftChild(new SearchNode(50,"50"));
        root.getRightChild().setLeftChild(new SearchNode(45,"45"));
        root.getRightChild().setRightChild(new SearchNode(35,"35"));
        StringBuffer sin = new StringBuffer();
        t.toSerial(root,sin);
        System.out.println(sin.toString());*/
        String ss = "30-10-50-#-#-#-20-45-#-#-35-#-#-";
        String[] arr = ss.split("-");
        Queue<String> queue = new LinkedList<String>();
        for (String s : arr) {
            queue.add(s);
        }
        String first = queue.poll();
        SearchNode myroot = new SearchNode(Integer.parseInt(first), first);
        t.toTree(myroot, queue);
        System.out.println(myroot.toString());
    }
}




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

二叉树4:二叉树的序列化和反序列化
  • qq_27703417
  • qq_27703417
  • 2017-05-02 22:32:55
  • 1087

剑指offer-二叉树的序列化和反序列化(困惑)-Java

今天在牛客上做这个题,发现一个很奇怪的事,以下第一个代码能AC,第二个却不能,但其实我个人觉得第二个更好,也不知道牛客的测试用例是怎么写的。 题目描述 请实现两个函数,分别用来序列化和反序列化...
  • d12345678a
  • d12345678a
  • 2017-01-07 22:15:29
  • 747

二叉树的序列化和反序列化实现(C++)

题目: 实现二叉树的序列化和反序列化的函数。 思路:         二叉树的序列化 即给定二叉树的头指针,按照某种遍历方式将所有结点链接为一个数组或字符串(/指针)。        ...
  • u013575812
  • u013575812
  • 2015-12-05 14:39:49
  • 1493

序列化和反序列化二叉树(java版)

【题目描述】请实现两个函数,分别用来序列化和反序列化二叉树【解题思路1】 //1. 利用前序遍历序列化二叉树,然后从记录的字符串中反序列化二叉树。 //2. 遇到空节点需要用特殊字符加以标记。如“...
  • ouyangyanlan
  • ouyangyanlan
  • 2017-06-06 11:15:04
  • 2324

二叉树的序列化和反序列化(C++) (leetcode)

考点: http://blog.csdn.net/weiwei22844/article/details/42004983参考其中的一个解题方法http://blog.csdn.net/bruceh...
  • qq_26437925
  • qq_26437925
  • 2016-07-15 09:34:50
  • 373

LintCode 7-二叉树的序列化和反序列化

本人电子系,只为一学生。心喜计算机,小编以怡情。设计一个算法,并编写代码来序列化和反序列化二叉树。将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”。如何反序列化或序列化二...
  • Jason__Liang
  • Jason__Liang
  • 2017-01-06 15:12:25
  • 581

Python:序列化二叉树

牛客网上的剑指 offer的在线编程: 题目描述 请实现两个函数,分别用来序列化和反序列化二叉树 class TreeNode: def __init__(self, x...
  • Lynette_bb
  • Lynette_bb
  • 2017-07-14 18:42:55
  • 403

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

题目描述 请实现两个函数,分别用来序列化和反序列化二叉树 # -*- coding:utf-8 -*- # class TreeNode: # def __init__...
  • You_are_my_dream
  • You_are_my_dream
  • 2017-01-28 19:43:07
  • 710

(lintcode)第7题二叉树的序列化和反序列化

设计一个算法,并编写代码来序列化和反序列化二叉树。将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”。 如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列...
  • Aphysia
  • Aphysia
  • 2017-08-29 01:37:14
  • 725

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

该题首先用先序遍历的思路把树转换(序列化)为字符串,这样在恢复的时候就可以根据字符串先序遍历的特点进行恢复(反序列化)。 string int2str(int intsrc){ ...
  • muguangzhilian
  • muguangzhilian
  • 2015-09-01 20:56:28
  • 439
收藏助手
不良信息举报
您举报文章:序列化/反序列化二叉树,代码是自己写的
举报原因:
原因补充:

(最多只允许输入30个字)