c++ - 合并排序导致堆栈溢出?

标签 c++ linked-list stack-overflow mergesort

我用 C++ 为链表编写了 mergesort()。问题是我的教授提供了一个非常大的列表(长度为 575,000)的测试代码。这会导致我的函数发生堆栈溢出错误,因为它是递归编写的。

所以我的教授可能希望我们使用迭代而不是递归来编写它。我想问下是不是我的代码有什么问题导致栈溢出?

我的代码:

typedef struct listnode {
    struct listnode * next;
    long value; 
} LNode;

LNode* mergesort(LNode* data) {
    if(data == NULL || data->next == NULL) {
        return data;
    }else {
        LNode* s = split(data);

        LNode* firstSortedHalf = mergesort(data);
        LNode* secondSortedHalf = mergesort(s);

        LNode* r = merge(firstSortedHalf, secondSortedHalf);
        return r;
    }
}

LNode* split(LNode* list) {
    if(list) {
        LNode* out = list->next;

        if(out) {
            list->next = out->next;
            out->next = split(out->next);
        }
        return out;
    }else {
        return NULL;
    }
}

LNode* merge(LNode* a, LNode* b) {
    if(a == NULL)
        return b;
    else if(b == NULL)
        return a;

    if(a->value < b->value) {
        a->next = merge(a->next,b);
        return a;
    }else {
        b->next = merge(a, b->next);
        return b;
    }
}

最佳答案

所以你有三个递归函数。让我们看一下每个元素的最大深度,其中包含 575000 个元素的列表的最坏情况:

  • merge():这看起来会遍历整个列表。所以 575000 个堆栈帧。
  • split():这看起来是成对迭代整个列表。所以 ~250000 个堆栈帧。
  • mergesort():这看起来以拆分方式进行迭代。所以 log_2(575000) 或大约 20 个堆栈帧。

因此,当我们运行我们的程序时,我们会获得有限的堆栈空间来容纳我们所有的堆栈帧。在我的计算机上,默认限制约为 10 兆字节。

粗略估计每个堆栈帧占用 32 个字节。对于 merge() 的情况,这意味着它将占用大约 18 MB 的空间,这远远超出了我们的限制。

虽然 mergesort() 调用自身,但只有 20 次迭代。这应该符合任何合理的限制。

因此,我的结论是,merge()split() 不应以递归方式实现(除非该方式是尾递归且已开启优化) .

关于c++ - 合并排序导致堆栈溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28663226/

相关文章:

java - 为什么 setNext 在 add (to front) 方法那里?

C++链表从最高到最低错误排序

C++:链表和指针乐趣

java.lang.StackOverflowError。为什么我在这里收到 Stackoverflow 异常

c++ - vector 析构函数在 _CrtIsValidHeapPointer 处失败

c++ - boost::pool_allocator 需要八个静态库?

c++ - 如何读写数组中的图像?

c++ - 将变量作为函数参数传递时由于隐式转换导致精度损失

JavaScript 堆栈溢出错误

c++ - 大小为 1 MB 的数组