【问题标题】:Reversing singly linked list using recursion使用递归反转单链表
【发布时间】:2018-11-16 02:50:48
【问题描述】:

我已经编写了代码来使用递归来反转单链表。它在长度小于或等于 174725 的列表上工作正常。但在长度大于 174725 的列表上,它会在通过 reverse() 调用反转它时给出分段错误(分段错误:11)。有人可以向我解释一下吗?

#include <iostream>
using namespace std;

class Node
{
  public:
    int val;
    Node *next;
};

class Sll
{
  public:
    Node *head;

  private:
    void reverse(Node *node);

  public:
    Sll();
    void insert_front(int key);
    void reverse();
    void print();
};

void Sll::reverse(Node *node)
{
    if (node == NULL) return;
    Node *rest = node->next;
    if (rest == NULL)
    {
        head = node;
        return;
    }
    reverse(rest);
    rest->next = node;
    node->next = NULL;
    return;
}

Sll::Sll()
{
    head = NULL;
}

void Sll::insert_front(int key)
{
    Node *newnode = new Node;
    newnode->val = key;
    newnode->next = head;
    head = newnode;
    return;
}

void Sll::print()
{
    Node *temp = head;
    while (temp)
    {
        temp = temp->next;
    }
    cout << endl;
    return;
}

void Sll::reverse()
{
    reverse(head);
    return;
}

int main()
{
    Sll newList = Sll();
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) newList.insert_front(i + 1);
    newList.reverse();
    // newList.print();
    return 0;
}

【问题讨论】:

    标签: c++11 segmentation-fault singly-linked-list


    【解决方案1】:

    列表反转函数必须是尾递归的,否则在递归长列表时它会溢出堆栈,就像你观察到的那样。此外,它需要在启用优化或使用-foptimize-sibling-calls gcc 选项的情况下进行编译。

    尾递归版本:

    Node* reverse(Node* n, Node* prev = nullptr) {
        if(!n)
            return prev;
        Node* next = n->next;
        n->next = prev;
        return reverse(next, n);
    }
    

    迭代列表还原可以更容易地内联,并且不需要任何优化选项:

    inline Node* reverse(Node* n) {
        Node* prev = nullptr;
        while(n) {
            Node* next = n->next;
            n->next = prev;
            prev = n;
            n = next;
        }
        return prev;
    }
    

    【讨论】:

    • "递归函数一般不能内联。"为什么不呢?
    • 这是我的新 reverse() 调用,它以尾递归方式编码。但同样的问题仍然存在。
    • @TusharVatsal 它需要在启用优化或-foptimize-sibling-calls gcc 选项的情况下进行编译。
    • @Maxim Egorushkin 即使应用了这种优化,我也遇到了分段错误
    • @TusharVatsal 我没有得到-O3 的段错误。未测试其他优化级别。
    猜你喜欢
    • 2018-12-03
    • 1970-01-01
    • 2020-07-22
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    相关资源
    最近更新 更多