使用递归

时间:2018-06-06 12:08:54

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

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

#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;
}

1 个答案:

答案 0 :(得分:2)

列表反转函数必须是尾递归的,否则它会在递归长列表时溢出堆栈,就像你观察到的那样。此外,它需要在启用优化或使用-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;
}