简体   繁体   English

通过预遍历构建二叉树:堆栈溢出错误

[英]Build Binary Tree from Preorder Traversal: Stack Overflow Error

I have a tree where the leaves are marked with L and the non-leaf nodes are marked with I. I am given the preorder traversal of the tree. 我有一棵树,叶子用L标记,非叶子节点用I标记。得到树的预遍历。 An example is IIILLILILLIIILLLIILILLL. 一个例子是IIILLILILLIIILLLIILILLL。 I have to build the huffman tree for this included string. 我必须为此包含的字符串构建霍夫曼树。 I originally pass in a new Root(), 0, and my treeString for my arguments. 我最初传入一个新的Root(),0和我的treeString作为参数。 TreeString would be the string with the I's and L's pasted above. TreeString是上面带有I和L的字符串。 For some reason my code causes a StackOverflow exception to be thrown. 由于某种原因,我的代码导致引发StackOverflow异常。 My code is as follows for the makeTree method: 对于makeTree方法,我的代码如下:

public static void makeTree (BinaryNodeInterface<Character> root, int start, String treeString)
{
    if (treeString.charAt(start)=='L'){

        root.setLeftChild(null);
        root.setRightChild(null);
        return;
    }
    BinaryNodeInterface<Character> leftSide = new BinaryNode<Character>();
    root.setLeftChild(leftSide);
    makeTree(root.getLeftChild(), start++, treeString);
    BinaryNodeInterface<Character> rightSide = new BinaryNode<Character>();
    root.setRightChild(rightSide);
    makeTree(root.getRightChild(), start++, treeString);
}

I have no idea what is causing the stackoverflow exception to be thrown. 我不知道是什么导致引发stackoverflow异常。 I would think that my base case at the beginning would return and handle it. 我认为一开始我的基本情况将返回并处理。

I believe this is the problem: 我相信这是问题所在:

makeTree(root.getLeftChild(), start++, treeString);

I'm not sure what your approach is, but it looks like if you see an I , your plan is to go to the left node, and start examining the string starting at the next character. 我不确定您的处理方法是什么,但是如果您看到I ,则您的计划是转到左节点,然后开始检查从下一个字符开始的字符串。

The reason for the infinite recursion is that start++ is a post-increment operator, which means that it gives you the current value of start and then increments it. 无限递归的原因是start++是后递增运算符,这意味着它会为您提供start的当前值,然后对其进行递增。 Thus, each time makeTree calls itself, it calls itself with the same version of start , and thus looks at the same I in the input string. 因此,每次makeTree调用自身时,都会使用相同版本的start调用,从而在输入字符串中查找相同的I

However, changing it to ++start will not make things work. 但是,将其更改为++start将无法正常工作。 (It might avoid the stack overflow, but it won't work right.) The reason is that when you call makeTree , you want to give it the starting location of the string where you want the recursive call to start looking--but you also want the recursive call to tell it how much of the string it consumed. (这可以避免堆栈溢出,但是不能正常工作。)原因是,当您调用makeTree ,您想给它一个字符串的起始位置,您希望在该位置开始递归调用,但是您还希望递归调用告诉它消耗了多少字符串。 That is necessary because, after makeTree calls itself recursively on getLeftChild , you will call it again on getRightChild , and you need to call it with the correct starting point. 这是必要的,因为在makeTreemakeTree上递归调用自身getLeftChild ,您将在getRightChild再次调用它,并且需要以正确的起点进行调用。

Note that each recursive invocation has its own copy of start . 请注意,每个递归调用都有其自己的start副本。 Thus, when makeTree calls itself, and the second makeTree increments start , this has no effect on the start that the first makeTree sees. 因此,当makeTree调用自身并且第二个makeTree递增start ,这对第一个makeTree看到的start没有影响。

You'll somehow need each recursive makeTree to tell its caller how much of the string it consumed. 您将以某种方式需要每个递归的makeTree来告诉其调用者它消耗了多少字符串。 Probably, the simplest way to do this is to change the return type to int ; 可能最简单的方法是将return类型更改为int you can decide whether you want the function result to be the number of characters consumed, or the index where it stopped scanning, or something similar. 您可以决定是否希望函数结果是消耗的字符数,停止扫描的索引或类似内容。 Then, after calling makeTree recursively, use the function result to adjust the start parameter. 然后,在递归调用makeTree之后,使用函数结果调整start参数。 Make sure makeTree returns the correct result, both in the leaf and the non-leaf cases. 确保makeTree在叶子和非叶子情况下都返回正确的结果。 Be careful to avoid off-by-one errors. 小心避免出现一对一的错误。

You cannot create a tree just from preOrder list. 您不能仅从preOrder列表创建树。 Atleast you need inorder traversal as well OR if is full tree then you can also use posrorder. 至少您还需要顺序遍历,或者如果是完整树,则也可以使用后序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM