我的问题与我发现的结果略有不同,我在很长一段时间内没有使用过Java(新手),所以我需要澄清一下。
基本上,我很确定我的实施大多是正确的,我只是想对我正在做的事情给出一些背景故事。
所以,我真正的问题是我已经将二叉树序列化为字符串:
1
2 3
4 5
为:
1 2 4 # # 5 # # 3 # #
其中#只是空节点。
当我尝试从字符串重建它时,我的问题就来了。我已经做了几个小时的挖掘工作,但我认为我过于复杂了。我只需要知道读取字符串的最简单方法(由空格分隔):
第一个元素是1,因此我们将其更改为int并使用该元素作为元素。接下来是2,所以同样,然后4.接下来是#,所以我们忽略它,因为没有叶子等。
然后,我需要将字符串的剩余部分(减去已经从前面读过的部分)发送到递归调用中。
总之,我的问题基本上是“如上所述解析它的最简单方法,并将剩余的字符串发送到递归调用中?”
答案 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;
}