从字符串反序列化Java二进制树

时间:2011-11-13 21:56:09

标签: java serialization tree binary-tree

我的问题与我发现的结果略有不同,我在很长一段时间内没有使用过Java(新手),所以我需要澄清一下。

基本上,我很确定我的实施大多是正确的,我只是想对我正在做的事情给出一些背景故事。

所以,我真正的问题是我已经将二叉树序列化为字符串:

      1
   2     3
 4   5

为:

1 2 4 # # 5 # # 3 # #

其中#只是空节点。

当我尝试从字符串重建它时,我的问题就来了。我已经做了几个小时的挖掘工作,但我认为我过于复杂了。我只需要知道读取字符串的最简单方法(由空格分隔):

第一个元素是1,因此我们将其更改为int并使用该元素作为元素。接下来是2,所以同样,然后4.接下来是#,所以我们忽略它,因为没有叶子等。

然后,我需要将字符串的剩余部分(减去已经从前面读过的部分)发送到递归调用中。

总之,我的问题基本上是“如上所述解析它的最简单方法,并将剩余的字符串发送到递归调用中?”

5 个答案:

答案 0 :(得分:1)

在将树序列化为字符串时,我会使用括号:

1(2(3 4) 5(6))

描述树:

         1
       /   \
      /     \
     /       \
    2         5
   / \       / 
  /   \     /    
 3     4   6      

当你只有一个孩子时会有一些歧义,因为你无法判断孩子是左孩子还是右孩子。在这种情况下,您可以拥有一个明确的“无子”字符:

1(2(3 4) 5(# 6))     //6 is the right child
1(2(3 4) 5(6 #))     //6 is the left child

因此,在解析它时,无论何时遇到左括号,您都会查看当前节点的子节点。当您遇到右括号时,您知道您已完成该节点的子节点,因此您可以回到上一级别。

答案 1 :(得分:1)

使用这个java方法..consider你有字符串数组......

private static Tree<Integer> deserialize(Tree<Integer> tree,
        String[] stringArray) {
    // TODO Auto-generated method stub
    if(index>=stringArray.length)
        return null;
    if(stringArray[index].equals("#")){
        index++;
        return null;

    }
    int value=Integer.parseInt(stringArray[index]);
    tree=new Tree<Integer>(value);
    index++;
    tree.left=deserialize(tree.left, stringArray);
    tree.right=deserialize(tree.right, stringArray);
    return tree;
}

答案 2 :(得分:1)

下面是我的序列化二进制和反序列化二叉树的代码。 我们只是将树预先转储到字符串中。 在这里,我使用了Rahul的代码,但我将其修改为更简洁。

public class DeSerializationBinaryTree {
    public static String serialize(Node root) {
        if (root == null)
            return "# ";
        else {
            return root.val + " " + serialize(root.left) + serialize(root.right);
        }
    }

    public static Node deserialize(String res) {
        String[] tokens = res.trim().split("\\s+");
        return deserialize(tokens);
    }

    static int index = 0;

    private static Node deserialize(String[] stringArray) {
        if (index >= stringArray.length)
            return null;
        if (stringArray[index].equals("#")) {
            index++;
            return null;
        }

        int value = Integer.parseInt(stringArray[index]);
        Node tree = new Node(value);
        index++;
        tree.left = deserialize(stringArray);
        tree.right = deserialize(stringArray);
        return tree;
    }

    private static void inorder(Node root) {
        if (root != null) {
            inorder(root.left);
            System.out.println(root.val);
            inorder(root.right);
        }
    }

    public static void main(String[] args) {
        Node root = new Node(30);
        Node node1 = new Node(10);
        Node node2 = new Node(20);
        Node node3 = new Node(50);
        Node node4 = new Node(45);
        Node node5 = new Node(35);
        root.left = node1;
        root.right = node2;
        node1.left = node3;
        node2.left = node4;
        node2.right = node5;

        System.out.println(serialize(root));
        Node node = deserialize("30 10 50 # # # 20 45 # # 35 # # ");
        inorder(node);
    }
}

答案 3 :(得分:0)

  

我只需要知道读取字符串的最简单方法(由空格分隔)

从字符串中创建Scanner,并使用hasInt() / nextInt()next()。像这样:

    Scanner s = new Scanner(inputString);
    s.setDelimiters("\\s+");
    ...

    if (s.hasInt()) {
        int = s.nextInt();
        // ... create a node and recurse twice to populate its children
    } else if (s.next().equals("#")) {
        // ... this is a null node
    } else {
        // ... syntax error
    }

答案 4 :(得分:0)

private int index =0;  

/**
 * Saves this tree to a file.
 * @param filename the name of the file in which to save this tree; 
 *              if null, uses default file name
 * @return   <code>true</code> if successful save
 *          <code>false</code> otherwise
 * @throws IOException if unexpected IO error 
 */

public final boolean save(String filename) throws IOException{
    List<String> sbtList = new ArrayList<>();
    sbtList = preOrderSerialize(this, sbtList);
    for (String sbtList1 : sbtList) {
        System.out.println(sbtList1);
    }
    try{
        OutputStream file = new FileOutputStream (filename);
        OutputStream buffer = new BufferedOutputStream(file);
        output = new ObjectOutputStream(buffer);
        output.writeObject(sbtList);

    }catch (IOException e){
        System.err.println("Save not successful" + e);
        return false;
    }
    finally { 
        output.close(); 
    }
   return true;
}
/**
 * The pre-order traversal to serialize a binary tree
 * @param sbt
 * @return
 * @throws IOException 
 */
private List<String> preOrderSerialize(StringBinaryTree sbt, List<String> myList){ 
    if (sbt == null){ 
        myList.add("# ");
    }           
    else{
        //sbt.add(this.value + "");
        myList.add(this.value + " ");
        preOrderSerialize(sbt.leftNode, myList);
        preOrderSerialize(sbt.rightNode, myList);
    }
   return myList;
}

/**
 * Restores this tree from a file. 
 * @param filename the name of the file from which to restore the tree;
 * if <code>null</code>, uses default file name.
 * @return <code>true</code> if successful restore
 *          <code>false</code> otherwise
 * @throws IOException if there is an IO issue
 */
public final boolean restore(String filename) throws IOException{
    try {
        InputStream file = new FileInputStream (filename);
        InputStream buffer = new BufferedInputStream (file);
        input = new ObjectInputStream(buffer);
        try{
            List <String> restoreSBT = (List<String>)input.readObject();
            StringBinaryTree root = deSerialize (restoreSBT);
        } finally {
            input.close();
        }
    }
    catch(IOException ex){
        System.err.println("File Not Restored" + ex);
        return false;
    }
    catch (ClassNotFoundException e){
        System.err.println("Cannot read file: Class Not Found"+ e);
        return false;
    }
    return true;
}

private StringBinaryTree deSerialize(List<String> restoreSBT ){
    if (index >= restoreSBT.size()){
        return null; 
    }
    if (restoreSBT.get(index).equals("#")){
        index ++;
        return null;
    }
    StringBinaryTree root = new StringBinaryTree (restoreSBT.get(index));
    index++;
    root.leftNode = deSerialize(restoreSBT);
    root.rightNode = deSerialize(restoreSBT);
    return root;
}