我编写了使用递归来反转单链表的代码。它在长度小于或等于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;
}
答案 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;
}