【问题标题】:Recursively turning a stack into a linked list递归地将堆栈变成链表
【发布时间】:2016-09-30 13:01:44
【问题描述】:

所以我一直在从事一项编程任务,该任务涉及采用大小约为 13,000 的堆栈实现并将其转换为链表。该指南基本上是通过顺序扫描链表来填充堆栈(IE尾部将是堆栈的顶部),并且您想使用堆栈重新创建链表。诀窍是你必须使用递归方法来做到这一点。此堆栈类中的唯一方法是 pop(返回并删除顶部元素)和 isEmpty(判断堆栈是否为空)。我有完成工作的代码,但是它需要增加 java 堆栈大小(否则我会得到 StackOverflowError),我觉得这是不允许的。

话虽如此,有谁知道我可以在不增加 java 堆栈大小的情况下使其工作的方法。

堆栈是我标记为 S 的静态字段。Head 应该是链表中的第一个节点,而 steper 只是用于创建其他每个步骤的节点。

这是我目前拥有的代码:

public static void stackToList()
{
    int x = 0;
        if(S.isEmpty())
        {
            return;
        }
        x = S.pop();
        stackToList();
        if (head == null)
        {
            head = new ListNode(x, null);
            steper = head;
        }
        else
        {
            steper.next = new ListNode(x, null);
            steper = steper.next;
        }

}

提前感谢您的帮助。

【问题讨论】:

  • 出于好奇,堆栈中有什么?
  • 只有很多整数。没有什么特别的。
  • 澄清一下,当您说“堆栈大小”时,您指的是递归调用期间的 Java 调用堆栈吗?因为如果你正在阅读它,你堆叠的“S”不会增加!
  • 当我说我增加堆栈大小时,我的意思是在运行配置中添加了一个参数,例如 -Xss2m

标签: recursion


【解决方案1】:

这是因为您将整个函数调用列表保存在内存堆栈中。只有在到达堆栈底部后才开始创建链接列表,从而保持之前对 stackList 的所有调用等待结束。

您需要从堆栈的第一个弹出窗口开始创建您的链表。

一个简单且未经测试的(很久没有在 Java 中工作过)的函数可能如下所示:

public static ListNode stackToList(ListNode head) {
    if(S.isEmpty())
        return head;

    int stackValue = S.pop();
    ListNode node = ListNode(stackValue, null);
    node.next(head);
    return stackToList(node);
}

你这样称呼它:

ListNode head = stackToList(null)

HTH

编辑:现在我发布了它,我意识到我的代码可能与你的问题相同,因为我记得Java doesn't support tail-call optimization。

【讨论】:

  • 对不起,我在学校反应迟钝。就创建相同的列表而言,您的代码可以正常工作,但它也会遇到堆栈溢出。在这一点上,我刚刚将它包装在一个 try catch 中,因为 catch 再次调用该方法。显然这远非理想,但教授现在已经明确表示我们不能增加 java 堆栈大小,所以我不知道我们如何解决它。
【解决方案2】:

如果您使用java.util.LinkedList 和java.util.Stack,您的问题并不完全清楚,但由于您没有提供这些对象的代码,我将在下面的示例解决方案中使用它们:

public static void main(String[] args) {
    //Create a stack
    Stack<Integer> stack = new Stack<Integer>();
    stack.push(0);
    stack.push(1);
    stack.push(2);
    stack.push(3);
    stack.push(4);
    stack.push(5);
    stack.push(6);
    stack.push(7);
    stack.push(8);
    stack.push(9);

    //Create a list to hold your stack elements
    LinkedList<Integer> linkedList = new LinkedList<Integer>();

    //Call the conversion method, which modifies both the stack and the list
    convertStackToLinkedList(stack, linkedList);

    //print the results
    System.out.println("linkedList: "+linkedList);
}

public static void convertStackToLinkedList(Stack<Integer> stack, LinkedList<Integer> linkedList){
    int topStackElement = stack.pop();
    linkedList.add(0,topStackElement);
    if(!stack.isEmpty())
        convertStackToLinkedList(stack, linkedList);
}

我怀疑您可能没有使用java.util.LinkedList,因为您的代码正在尝试修改列表的内部结构。因此,您只需要在java.util.LinkedList 类中实现类似于add(int index, E element) 方法的方法,然后在递归中使用它。如果您可以访问列表的内部,我假设您可以这样做。

编辑:

我忘了提到我同意 Harsh Gupta 的回答,因为您看到 StackOverflowError 的原因是您正在等待直到递归结束来修改您的列表。在某些递归中,您必须等到结束,但如果您不必等待,请不要这样做。

【讨论】:

    猜你喜欢
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    • 1970-01-01
    • 2011-11-24
    • 2015-06-06
    • 2011-01-30
    • 2013-06-09
    相关资源
    最近更新 更多