Java 序列化和反序列化类似Trie的数据结构

Java 序列化和反序列化类似Trie的数据结构,java,recursion,serialization,deserialization,trie,Java,Recursion,Serialization,Deserialization,Trie,我正在尝试序列化和反序列化一个类似Trie的数据结构,它在每个节点中都有数据/字符。所以,要形成一个完整的单词,需要从根节点遍历到叶节点 序列化和反序列化应在预顺序遍历中进行,即在DFS方法中处理子级 #标记该节点的遍历结束,即类似trie的节点不再具有任何子节点 这是我试过的 public class SerializeDeserialize { public static void main(String[] args) { // prepare TrieNode

我正在尝试序列化和反序列化一个类似Trie的数据结构,它在每个节点中都有数据/字符。所以,要形成一个完整的单词,需要从根节点遍历到叶节点

序列化和反序列化应在预顺序遍历中进行,即在DFS方法中处理子级

#
标记该节点的遍历结束,即类似trie的节点不再具有任何子节点

这是我试过的

public class SerializeDeserialize {

    public static void main(String[] args) {
        // prepare TrieNode Tree
        TrieNodeSD root = buildTrienodeTree();
        StringBuilder sb = new StringBuilder();
        serialize(root, sb);
        sb.deleteCharAt(sb.length()-1);
        System.out.println(sb.toString());
        System.out.println();
        TrieNodeSD newRoot = deserialize(sb.toString().split(","), new int[] {0});
        StringBuilder newsb = new StringBuilder();
        serialize(newRoot, newsb);
        newsb.deleteCharAt(newsb.length()-1);
        System.out.println(newsb.toString());
    }

    private static void serialize(TrieNodeSD node, StringBuilder sb) {
        if (node == null) return;
        sb.append(node.character + ",");
        if (node.characters != null && node.characters.size() > 0) {
            for (Character c : node.characters.keySet()) {
                serialize(node.characters.get(c), sb);
            }
        }
        sb.append("#,");
    }

    // DOESN'T WORK!!
    private static TrieNodeSD deserialize(String[] data, int[] t) {
        if (t[0] >= (data.length-1) || data[t[0]].equals("#")) return null;
        TrieNodeSD node = new TrieNodeSD(data[t[0]].charAt(0));
        t[0] = t[0] + 1;
        TrieNodeSD child = deserialize(data, t);
        if (child != null) node.characters.put(child.character, child);
        return node;
    }

    private static TrieNodeSD buildTrienodeTree() {
        TrieNodeSD root = new TrieNodeSD('A');

        root.characters.put('B', new TrieNodeSD('B'));
        root.characters.get('B').characters.put('E', new TrieNodeSD('E'));
        root.characters.get('B').characters.put('F', new TrieNodeSD('F'));
        root.characters.get('B').characters.get('F').characters.put('K', new TrieNodeSD('K'));

        root.characters.put('C', new TrieNodeSD('C'));

        root.characters.put('D', new TrieNodeSD('D'));
        root.characters.get('D').characters.put('G', new TrieNodeSD('G'));
        root.characters.get('D').characters.put('H', new TrieNodeSD('H'));
        root.characters.get('D').characters.put('I', new TrieNodeSD('I'));
        root.characters.get('D').characters.put('J', new TrieNodeSD('J'));

        return root;
    }
}

class TrieNodeSD {
    Map<Character, TrieNodeSD> characters;
    char character;
    public TrieNodeSD(char c) {
        this.characters = new HashMap<Character, TrieNodeSD>();
        this.character = c;
    }
    @Override
    public String toString() { return this.character + "";  }
}
public类序列化反序列化{
公共静态void main(字符串[]args){
//准备三元树
trineodesd root=buildtrineodetree();
StringBuilder sb=新的StringBuilder();
序列化(root,sb);
sb.deleteCharAt(sb.length()-1);
System.out.println(sb.toString());
System.out.println();
三元组newRoot=反序列化(sb.toString().split(“,”),新int[]{0});
StringBuilder newsb=新的StringBuilder();
序列化(newRoot、newsb);
newsb.deleteCharAt(newsb.length()-1);
System.out.println(newsb.toString());
}
私有静态void序列化(三节点,StringBuilder sb){
if(node==null)返回;
sb.追加(node.character+“,”);
if(node.characters!=null&&node.characters.size()>0){
对于(字符c:node.characters.keySet()){
序列化(node.characters.get(c),sb);
}
}
某人加上(“#,”);
}
//没用!!
私有静态三节点反序列化(字符串[]数据,int[]t){
如果(t[0]>=(data.length-1)| | data[t[0]].equals(“#”)返回null;
三元节点=新的三元节点(数据[t[0]].charAt(0));
t[0]=t[0]+1;
三节点子节点=反序列化(数据,t);
if(child!=null)node.characters.put(child.character,child);
返回节点;
}
私有静态三节点构建三节点树(){
三节点D根=新的三节点D('A');
root.characters.put('B',新的三元组('B');
root.characters.get('B').characters.put('E',新的三元组('E'));
root.characters.get('B').characters.put('F',新的三元组('F'));
root.characters.get('B').characters.get('F').characters.put('K',新三元组('K'));
root.characters.put('C',新的三元组('C');
root.characters.put('D',新的三元组('D');
root.characters.get('D').characters.put('G',新的三元组('G'));
root.characters.get('D').characters.put('H',新的三元组('H'));
root.characters.get('D').characters.put('I',new-trieodesd('I'));
root.characters.get('D').characters.put('J',新的三元组('J');
返回根;
}
}
三节点类{
地图字符;
字符;
公共三元组D(字符c){
this.characters=new HashMap();
这个字符=c;
}
@凌驾
公共字符串toString(){返回this.character+“”;}
}
序列化以预排序格式提供输出(例如,
A、B、e、#、F、K、#、#、#、C、#、D、g、#、H、#、I、#、J、#、#、#、#、#

问题:
在反序列化过程中,代码不会正确处理所有子级,也不会将它们与正确的父级关联


有人能建议如何修复
反序列化
方法中的处理,或者帮助我找到指针我缺少了什么吗?

不太确定您的
trie数据结构,但是如果您指的是
trie
,那么一定会有一些误解

有一个明确的规范

…与二叉搜索树不同,树中没有节点存储与该节点关联的;相反,它在树中的位置定义了与之关联的键。一个节点的所有子节点都有一个与该节点关联的字符串的公共前缀,根与空字符串关联

(来自维基的内容,我只是增加了重点)

问题:在反序列化过程中,代码不会正确处理所有子级,也不会将它们与正确的父级关联

即使对于节点中有键的树结构,您的解决方案仍然无法工作,因为您使用
映射而不是
固定大小的
数组来忽略子节点的大小,这对于反序列化序列化数据非常重要

使用
map
无法确定哪个节点是父节点,哪个节点是子节点

对于
二叉搜索树
或实
三叉树
,它们的结构是预定义的,通过它们,您可以序列化反序列化,因为它们是确定性的


也许这才是你真正想要的

顺便说一下,您实际上可以在
*节点中直接序列化和反序列化

例如,序列化可以如下所示:

@Override
public String toString() {
    List<String> resultList = new ArrayList<>();
    for (TrieNode child : children) {
        if (child == null) resultList.add("#");
        else resultList.add(child.toString());
    }
    return resultList.stream().collect(Collectors.joining(","));
}
@覆盖
公共字符串toString(){
List resultList=new ArrayList();
for(三元组儿童:儿童){
if(child==null)resultList.add(“#”);
else resultList.add(child.toString());
}
返回resultList.stream().collect(collector.joining(“,”);
}

不太清楚您的
trie数据结构
,但是如果您指的是
trie
,那么肯定存在一些误解

有一个明确的规范

…与二叉搜索树不同,树中没有节点存储与该节点关联的;相反,它在树中的位置定义了与之关联的键。一个节点的所有子节点都有一个与该节点关联的字符串的公共前缀,根与空字符串关联

import java.util.HashMap;
import java.util.Map;

/**
 *                              A<br>
 *                  /           |           \<br>
 *                  B           C           D<br>
 *              /       \           /   /       \   \<br>
 *              E       F           G   H       I   J<br>
 *                      |<br>
 *                      K<br>
 * 
 *
 */
public class SerializeDeserialize {

    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        StringBuilder newsb = new StringBuilder();

        // prepare TrieNode Tree
        TrieNodeSD root = buildTrienodeTree();

        // serialize tree into string
        serialize(root, sb);
        sb.deleteCharAt(sb.length() - 1);
        System.out.println(sb.toString());
        System.out.println();

        // construct tree again from serialized string
        TrieNodeSD newRoot = deserialize(sb.toString().split(","), new int[] { 0 });

        // Verify : again serialize above de-serialized tree to match both
        // trees serialized format.
        serialize(newRoot, newsb);
        newsb.deleteCharAt(newsb.length() - 1);
        System.out.println(newsb.toString());
    }

    private static void serialize(TrieNodeSD node, StringBuilder sb) {
        if (node == null) return;
        sb.append(node.character + ",");
        if (node.characters != null && node.characters.size() > 0) {
            for (Character c : node.characters.keySet()) {
                serialize(node.characters.get(c), sb);
            }
        }
        sb.append("#,");
    }

    private static TrieNodeSD deserialize(String[] data, int[] t) {
        if (t[0] >= (data.length - 1) || data[t[0]].equals("#")) return null;
        TrieNodeSD node = new TrieNodeSD(data[t[0]].charAt(0));
        while (true) {
            t[0] = t[0] + 1;
            TrieNodeSD child = deserialize(data, t);
            if (child != null) node.characters.put(child.character, child);
            else break;
        }
        return node;
    }

    private static TrieNodeSD buildTrienodeTree() {
        TrieNodeSD root = new TrieNodeSD('A');

        root.characters.put('B', new TrieNodeSD('B'));
        root.characters.get('B').characters.put('E', new TrieNodeSD('E'));
        root.characters.get('B').characters.put('F', new TrieNodeSD('F'));
        root.characters.get('B').characters.get('F').characters.put('K', new TrieNodeSD('K'));

        root.characters.put('C', new TrieNodeSD('C'));

        root.characters.put('D', new TrieNodeSD('D'));
        root.characters.get('D').characters.put('G', new TrieNodeSD('G'));
        root.characters.get('D').characters.put('H', new TrieNodeSD('H'));
        root.characters.get('D').characters.put('I', new TrieNodeSD('I'));
        root.characters.get('D').characters.put('J', new TrieNodeSD('J'));

        return root;
    }
}

class TrieNodeSD {
    Map<Character, TrieNodeSD> characters;
    char character;

    public TrieNodeSD(char c) {
        this.characters = new HashMap<Character, TrieNodeSD>();
        this.character = c;
    }

    @Override
    public String toString() {
        return this.character + "";
    }
}
A,B,E,#,F,K,#,#,#,C,#,D,G,#,H,#,I,#,J,#,#,#

A,B,E,#,F,K,#,#,#,C,#,D,G,#,H,#,I,#,J,#,#,#