Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从路径编码重构二叉树?_Java_Encoding_Path_Binary Search Tree - Fatal编程技术网

Java 如何从路径编码重构二叉树?

Java 如何从路径编码重构二叉树?,java,encoding,path,binary-search-tree,Java,Encoding,Path,Binary Search Tree,假设我有以下形式的输入: (11,LL)(7,LLL)(8,R)(5,)(4,L)(13,RL)(2,LLR)(1,RRR)(4,RR)() 其中,第二个字段表示来自根节点的路径,空字段表示根节点,()表示数据结束 输出将是 级别顺序:54813134721 如何重建二叉树?请注意,有可能缺少节点。例如,LLL和L存在,但没有节点连接它们,在这种情况下,应该创建一个值为-1的节点来连接它们 到目前为止,我发现的是创建一个NodePath类,该类存储数据和路径,例如NodePath(11,LL)和

假设我有以下形式的输入:

(11,LL)(7,LLL)(8,R)(5,)(4,L)(13,RL)(2,LLR)(1,RRR)(4,RR)()

其中,第二个字段表示来自根节点的路径,空字段表示根节点,()表示数据结束

输出将是 级别顺序:54813134721

如何重建二叉树?请注意,有可能缺少节点。例如,LLL和L存在,但没有节点连接它们,在这种情况下,应该创建一个值为-1的节点来连接它们

到目前为止,我发现的是创建一个NodePath类,该类存储数据和路径,例如NodePath(11,LL)和字符串值。接下来,我遍历每个字符串标记。在迭代过程中,我比较路径长度并将它们存储在LinkedList中。 例如,11,LL-->7,LLL,当8出现时,它变为8,R-->11,LL-->7,LLL


现在,我陷入了困境,因为我不知道如何区分LLL和LLR,以及如何相应地构造二叉树。恐怕我会把LLL和LLR放在相反的位置。

你可以用键值对构建一个
映射图-键值是你的路径(“LLL”)和数值(“7”)


在第二步中,迭代映射
的入口集,自上而下构建每个路径,在没有默认值“-1”的位置创建新节点,并尽可能使用现有节点。

这是一个有趣的问题。我建议给树节点一个能力,让它们能够沿着一条路径在行进中构造节点。我将忽略所有用于解码字符串的代码,并跳转到构造的核心:

class Node {
    public enum Direction {
        L, R;
    }

    private int value = -1;
    private EnumMap<Direction, Node> children = new EnumMap<>(Direction.class);

    public Node nodeWithPath(List<Direction> path) {
        if (path.isEmpty()) {
            return this;
        } else {
            Direction direction = path.remove(0);
            if (!children.containsKey(direction))
                children.put(direction, new Node());
            return children.get(direction).nodeWithPath(path);
        }
    }
}

作为额外的(可能的)帮助,通过使用'L'和'R'作为枚举常量,您可以在Java 8中从字符串创建路径:

public void addValue(Node root, String pathString, int value) {
    List<Direction> path = Arrays.stream(pathString.toCharArray())
        .map(Character::toString)
        .map(Node.Direction::valueOf)
        .collect(Collectors.toList());
    root.nodeWithPath(path).setValue(value);
}
public void addValue(节点根、字符串路径字符串、int值){
列表路径=Arrays.stream(pathString.toCharArray())
.map(字符::toString)
.map(Node.Direction::valueOf)
.collect(Collectors.toList());
root.nodeWithPath(路径).setValue(值);
}

但是,如果您在学习Java的早期阶段,那么我刚刚编写的代码可能会让您感到困惑,而不是有帮助,因此请忽略它,使用传统的迭代或通过标记化进行解析:-)

这里有一个基于标记的解决方案

首先,节点的基本类:

public final class BinaryTreeNode
{
    private int value = -1;
    private BinaryTreeNode left = null;
    private BinaryTreeNode right = null;

    public int getValue()
    {
        return value;
    }

    public BinaryTreeNode getLeft()
    {
        return left;
    }

    public BinaryTreeNode getRight()
    {
        return right;
    }

    public void setValue(final int value)
    {
        this.value = value;
    }

    public void setLeft(final BinaryTreeNode left)
    {
        this.left = left;
    }

    public void setRight(final BinaryTreeNode right)
    {
        this.right = right;
    }
}
现在是生成器类:

public final class BinaryTreeBuilder
{
    private final BinaryTreeNode root = new BinaryTreeNode();

    private BinaryTreeNode current = root;

    private int nodeValue;

    public BinaryTreeNode getRoot()
    {
        return root;
    }

    public boolean setValue(final String match)
    {
        nodeValue = Integer.parseInt(match);
        return true;
    }

    public boolean moveLeft()
    {
        BinaryTreeNode node = current.getLeft();
        if (left == null) {
            node = new BinaryTreeNode();
            current.setLeft(node);
        }
        current = node;
        return true;
    }

    public boolean moveRight()
    {
        BinaryTreeNode node = current.getRight();
        if (right == null) {
            node = new BinaryTreeNode();
            current.setRight(node);
        }
        current = node;
        return true;
    }

    public boolean commitNode()
    {
        current.setValue(nodeValue);
        current = root;
        return true;
    }
}
最后,解析器:

public class BinaryTreeParser
    extends BaseParser<BinaryTreeNode>
{
    protected final BinaryTreeBuilder = new BinaryTreeBuilder();

    Rule endOfData()
    {
        return sequence("()", EOI);
    }

    Rule moves()
    {
        return firstOf(
            sequence('L', builder.moveLeft()),
            sequence('R', builder.moveRight())
        );
    }

    Rule oneNode()
    {
        return sequence(
            '(',
            sequence(oneOrMore(digit()), builder.setValue(match())),
            ',',
            zeroOrMore(moves()),
            ')', builder.commitNode();
        );
    }

    Rule allNodes()
    {
        return join(sequence(testNot(endOfData()), oneNode())
            .using(' ')
            .min(0);
    }

    public Rule fullTree()
    {
        return sequence(allNodes(), endOfData(), push(builder.getRoot());
    }
}
公共类二进制树解析器
扩展BaseParser
{
受保护的最终BinaryTreeBuilder=新BinaryTreeBuilder();
规则endOfData()
{
返回序列(“()”,EOI);
}
规则移动()
{
首先返回(
序列('L',builder.moveLeft()),
序列('R',builder.moveRight())
);
}
规则oneNode()
{
返回序列(
'(',
序列(一个或多个(数字()),builder.setValue(匹配()),
',',
零或更多(移动()),
“)”,builder.commitNode();
);
}
规则allNodes()
{
返回联接(序列(testNot(endOfData()),oneNode())
.使用(“”)
.min(0);
}
公共规则fullTree()
{
返回序列(allNodes()、endOfData()、push(builder.getRoot());
}
}
现在,您只需运行解析器并收集结果:

final BinaryTreeParser parser = Parboiled.createParser(BinaryTreeParser.class);

final ParseRunner<BinaryTreeNode> runner = new BasicParseRunner<>(parser.fullTree());

final ParsingResult<BinaryTreeNode> result = runner.run(yourInput);

if (result.isSuccess())
    tree = result.getTopStackValue();
final BinaryTreeParser=Parboiled.createParser(BinaryTreeParser.class);
final ParseRunner=new basicParserRunner(parser.fullTree());
最终parsingreult结果=runner.run(您的输入);
if(result.issucess())
tree=result.getTopStackValue();
因为grappa依赖于番石榴,而番石榴提供了一种新的颜色,所以您可以使用它来显示结果

当然,这种方法相当“复杂”;这里有一个更简单的方法:

  • 创建一个
    比较器
    ,该比较器进行如下比较:如果一个字符串较长,则该字符串大于另一个字符串;如果它们的长度相等,则应用规范排序
  • 创建一个
    TreeMap
    ,路径作为键,节点值作为值,上面的比较器作为键比较器
  • 将节点解析到地图中
  • 按顺序显示条目

但是请注意,在显示之前,您需要检查是否有根的条目,即空字符串。

您是否已经有一个对象来为树节点建模?作业?至少显示预期结果。当然很有趣。好吧,在插入节点的过程中插入任何缺失的节点。自动插入的节点将获得默认值价值
final BinaryTreeParser parser = Parboiled.createParser(BinaryTreeParser.class);

final ParseRunner<BinaryTreeNode> runner = new BasicParseRunner<>(parser.fullTree());

final ParsingResult<BinaryTreeNode> result = runner.run(yourInput);

if (result.isSuccess())
    tree = result.getTopStackValue();