Java-堆栈溢出错误

Java-堆栈溢出错误,java,stack-overflow,Java,Stack Overflow,我需要一些帮助 首先我有一个BinarySearchTree类 import java.util.ArrayList; import java.util.List; public class BinarySearchTree<E extends Comparable<? super E>> { private BSTNode<E> root; private int size; // root ==null iff size == 0 public B

我需要一些帮助

首先我有一个BinarySearchTree类

import java.util.ArrayList;
import java.util.List;

public class BinarySearchTree<E extends Comparable<? super E>> {

private BSTNode<E> root;
private int size;

// root ==null iff size == 0

public BinarySearchTree() {
    root = null;
    size = 0;
}


public boolean add(E value) {
    int oldSize = size;
    root = addHelper(root, value);
    return oldSize != size;
}

private BSTNode<E> addHelper(BSTNode<E> n, E val) {
    if (n == null) {
        n = new BSTNode<E>(null, val, null);
        size++;
    } else {
        int diff = val.compareTo(n.getData());
        if (diff < 0)
            n.setLeft(addHelper(n.getLeft(), val));
        else if (diff > 0)
            n.setRight(addHelper(n.getRight(), val));
    }
    return n;
}


public boolean remove(E value) {
    int oldSize = size;
    root = removeHelp(root, value);
    return oldSize != size;
}

// helper method for remove
private BSTNode<E> removeHelp(BSTNode<E> n, E val) {
    if (n != null) {
        int diff = val.compareTo(n.getData());
        if (diff < 0)
            n.setLeft(removeHelp(n.getLeft(), val)); // traverse the left
                                                     // side
        else if (diff > 0)
            n.setRight(removeHelp(n.getRight(), val)); // traverse right
                                                       // side
        else // if value is found
        {
            size--;
            if (n.getLeft() == null && n.getRight() == null) // if value
                                                             // contained in
                                                             // leaf, just
                                                             // make nul;
                n = null;
            else if (n.getRight() == null) // single child to left
                n = n.getLeft(); // move the child up to replace removed
                                 // node
            else if (n.getLeft() == null)
                n = n.getRight();
            else // two children, replace value with max of left subtree -
                 // it will not have a right subtree
            {
                n.setData(getMax(n.getLeft()));
                // now remove max of left subtree from its previous position
                n.setLeft(removeHelp(n.getLeft(), n.getData()));
                // add 1 back to size since size will be decremented from
                // this 2nd removal
                size++;
            }

        }
    }
    return n;
}

// helper method to find Max of a subtree
private E getMax(BSTNode<E> n) {
    while (n.getRight() != null)
        n = n.getRight();
    return n.getData();
}


public boolean isPresent(E value) {
    assert value != null : "Precondition failed: value != null";
    if (root == null)
        return false;
    return isPresentHelp(root, value);

}

public boolean isPresentHelp(BSTNode<E> n, E item) {
    if (n == null)
        return false;
    else {
        E temp = n.getData();
        // if item to search is greater than node, traverse right
        if (temp.compareTo(item) < 0)
            return isPresentHelp(n.getRight(), item);
        else if (temp.compareTo(item) > 0)
            return isPresentHelp(n.getLeft(), item);
        else
            return true;
    }
}


public int size() {
    return size;
}


public int height() {
    return heightHelper(root);
}

public int heightHelper(BSTNode<E> n) {
    int tempLeft, tempRight;
    if(n == null) 
        return -1;
    tempLeft = 1 + heightHelper(n.getLeft());
    tempRight = 1 + heightHelper(n.getRight());
    if(tempLeft > tempRight)
        return tempLeft;
    else 
        return tempRight;
}


public List<E> getAll() {
    List<E> result = new ArrayList<E>();
    return getAllHelp(root, result);
}

public List<E> getAllHelp(BSTNode<E> n, List<E> result) {

    if (n != null) {
        // traverse left to lowest value
        getAllHelp(n.getLeft(), result);
        // add to arraylist if it can go left no further (smallest current
        // value)
        result.add(n.getData());
        // traverse right if can't go left anymore
        getAllHelp(n.getRight(), result);

    }
    return result;
}


public E max() {
    return getMax(root);
}


public E min() {
    return getMin(root);
}

private E getMin(BSTNode<E> n) {
    while (n.getLeft() != null)
        n = n.getLeft();
    return n.getData();
}


public boolean iterativeAdd(E data) {
    BSTNode<E> n = root;
    while (n != null) {
        if (n.getData().compareTo(data) > 0) {
            if (n.getLeft() == null) {
                n.setLeft(new BSTNode<E>(data));
                size++;
                return true;
            } else
                n = n.getLeft();
        } else if (n.getData().compareTo(data) < 0) {
            if (n.getRight() == null) {
                n.setRight(new BSTNode<E>(data));
                size++;
                return true;
            } else
                n = n.getRight();
        } else
            return false;
    }
    root = new BSTNode<E>(null, data, null);
    size++;
    return true;
}


public E get(int kth) {
    assert 0 <= kth && kth < size() : "Precondition failed: 0 <= kth < size()";
    // keep track of which index recursive call is on (or the kth element)
    int count[] = { 0 };
    return getHelp(kth, root, count);
}

public E getHelp(int nth, BSTNode<E> n, int[] count) {
    E result = null;
    if (n != null) {
        result = getHelp(nth, n.getLeft(), count);
        if (result == null) {
            if (count[0] == nth) {
                return n.getData();
            } else {
                count[0]++;
                result = getHelp(nth, n.getRight(), count);
            }
        }
    }
    return result;
}


public List<E> getAllLessThan(E value) {
    List<E> result = new ArrayList<E>();
    return getAllLessHelp(root, result, value);
}

public List<E> getAllLessHelp(BSTNode<E> n, List<E> result, E value) {
    if (n != null) {
        getAllLessHelp(n.getLeft(), result, value);
        if (n.getData().compareTo(value) < 0) {
            result.add(n.getData());
        }
        getAllLessHelp(n.getRight(), result, value);
    }
    return result;
}


public List<E> getAllGreaterThan(E value) {
    List<E> result = new ArrayList<E>();
    return getAllGreaterHelp(root, result, value);
}

// returns the BSTNode containing the value
public List<E> getAllGreaterHelp(BSTNode<E> n, List<E> result, E value) {
    if (n != null) {
        if (n.getData().compareTo(value) > 0) {
            getAllGreaterHelp(n.getLeft(), result, value);
            result.add(n.getData());
        }
        getAllGreaterHelp(n.getRight(), result, value);
    }
    return result;
}

public int numNodesAtDepth(int d) {
    return numNodesHelp(d, root, 0);
}

public int numNodesHelp(int d, BSTNode<E> n, int count) {
    count = 0;
    if (n != null) {
        if (d == 0)
            count++;
        else {
            count += numNodesHelp(d - 1, n.getLeft(), count);
            count += numNodesHelp(d - 1, n.getRight(), count);
        }
    }
    return count;
}


public void printTree() {
    printTree(root, "");
}

private void printTree(BSTNode<E> n, String spaces) {
    if (n != null) {
        printTree(n.getRight(), spaces + "  ");
        System.out.println(spaces + n.getData());
        printTree(n.getLeft(), spaces + "  ");
    }
}


private static class BSTNode<E extends Comparable<? super E>> {
    private E data;
    private BSTNode<E> left;
    private BSTNode<E> right;

    public BSTNode() {
        this(null);
    }

    public BSTNode(E initValue) {
        this(null, initValue, null);
    }

    public BSTNode(BSTNode<E> initLeft, E initValue, BSTNode<E> initRight) {
        data = initValue;
        left = initLeft;
        right = initRight;
    }

    public E getData() {
        return data;
    }

    public BSTNode<E> getLeft() {
        return left;
    }

    public BSTNode<E> getRight() {
        return right;
    }

    public void setData(E theNewValue) {
        data = theNewValue;
    }

    public void setLeft(BSTNode<E> theNewLeft) {
        left = theNewLeft;
    }

    public void setRight(BSTNode<E> theNewRight) {
        right = theNewRight;
    }
}
}

嗯。谢谢大家的帮助。我真的很感激。你们回答得太快了:)

Java中堆栈的最大深度取决于分配的内存量,它表示

在这里,通过更大的测试,递归函数的深度已经达到极限。还提到32000是一个神奇的数字——不管怎样,您可以通过为堆栈分配更多内存来解决这个问题。如果希望能够处理10240000层的最坏情况,您可能需要分配很多

iterativeAdd
案例中出现错误的原因是,您正在反向添加元素:

 if (n.getData().compareTo(data) > 0) {
            if (n.getLeft() == null) {
                n.setLeft(new BSTNode<E>(data));
                size++;
                return true;
if(n.getData().compareTo(data)>0){
如果(n.getLeft()==null){
n、 setLeft(新节点(数据));
大小++;
返回true;
而不是:

int diff = val.compareTo(n.getData());
        if (diff < 0)
            n.setLeft(addHelper(n.getLeft(), val));
int diff=val.compareTo(n.getData());
如果(差异<0)
n、 setLeft(addHelper(n.getLeft(),val));

显然,这会导致树构建得更深,因此当您试图读回它时,会得到一个
StackOverflowerError

您的树根本不平衡,已退化为一个链表。由于您按顺序添加,它将继续添加到右侧,并且由于没有尝试平衡,节点将包含只有对的孩子


若要修复,请查看一些或以不同的顺序添加以使其平衡。不平衡的树效率低下,并且会降低算法的速度,因为查找和插入将在O(n)而不是O(log n)中进行时间。

StackOverflowerError
仅仅意味着您的程序超出了堆栈大小。这个错误是递归调用的最大危险,从发布的堆栈跟踪中我们可以看到,实际上它是
BinarySearchtTree.heightHelper
(第184行和第185行都进行递归调用)

所以我们剩下三个问题:

  • 什么是堆栈?它是一个具有LIFO访问模式的数据结构(最后一个推送到堆栈的元素是第一个将弹出的元素)
  • 我们谈论的是什么堆栈?JVM中的每个线程都有一个调用堆栈,这个调用堆栈在JVM启动时有一个固定的大小(您可以根据需要调整它)
  • 为什么堆栈溢出?当您进行方法调用时,运行时必须在某个地方存储本地变量和返回地址。这是线程堆栈。每次调用函数时,都会创建并推送一个新的堆栈帧;当函数返回时,该帧会从堆栈中弹出。如果您的实验失败,则对
    heightHelper
    的调用太多:每次递归调用都会推送另一个堆栈帧,此时没有空间进行另一个调用
  • 如何解决?您有两种选择:

  • 根据递归调用的预期数量,使用
    -ss
    参数调整JVM
  • 将您的实现更改为使用循环—编写代码可能更困难,但堆比堆栈大一个数量级,因此您不会遇到堆栈溢出

  • 多好的标题啊!我很高兴impressed@martialdidit:lolz..每个人都是:)史上关于StackOverflow的最好的问题。我花了很长时间才看到评论中的连接,我得到了一个StackOverflower错误。@atmin不是无限的,只是很深。如果它是无限的,每次都会出错。
     if (n.getData().compareTo(data) > 0) {
                if (n.getLeft() == null) {
                    n.setLeft(new BSTNode<E>(data));
                    size++;
                    return true;
    
    int diff = val.compareTo(n.getData());
            if (diff < 0)
                n.setLeft(addHelper(n.getLeft(), val));