当传递给函数时,奇异链表变为循环列表

Singular linked list become circular list when passed to a function

本文关键字:链表 列表 循环 函数      更新时间:2023-10-16

我正在尝试使用C++反转一个链表,然后打印出反转的链表。

例如:原始列表为1->2->3反转后:3->2->1

但当我试图打印出反向链表时,3->2->1变成了一个循环链表,就像3<->2

以下是我的代码:

#include <iostream>
#include <sstream>
using namespace std;
class List{
public:
    int value;
    List *next;
    List(int);
    List(int, List *);
};
List::List(int v){
    value = v;
    next = NULL;
}
List::List(int v, List *ne){
    value = v;
    next = ne;
}
string IntToString(int val){
    stringstream temp;
    temp<<val;
    return temp.str();
}
void print(List *l){
    string output= "";
    while(l->next != NULL){
        output+=(IntToString(l->value)+"-->");
        l = l->next;
    }
    output+=(IntToString(l->value)+"-->NULL");
    cout<<output<<endl;
}
List reverse(List L){
    if(L.next == NULL) return L;
    List remain = reverse(*(L.next));
    List *current = &remain;
    while(current->next != NULL)
        current = (current->next);
    L.next = NULL;
    current->next = &L;
    //print(remain);
    return remain;
}
List copy(List l){
    return l;
}
int main() {
    List L3(3);
    List L2(2, &L3);
    List L1(1, &L2);
    List L4 = reverse(L1);
    print(&L4);
    return 0;
}

有人能告诉我为什么会发生这种事吗?非常感谢!

首先,我想向您指出,包含指向another list的指针的list在概念上是错误的。

单独创建一个列表节点类,例如

struct ListNode {
    int value;
    Node *next;
};

然后你的List变成

class List {
    ...
    ListNode *head;
    ...
};

现在开始倒车。在方法List reverse( List L )中,L只是一个局部变量它在后超出范围,

    return remain;
} // Here the scope of L ends

因此,返回一个List,其next值是L的位置,在逻辑上是不正确的

current->next = &L;
return remain; // remain is equal to *current and current->next = &L

这会导致实现中出现未定义的行为

编辑:我有一些空闲时间,所以我想出了这个实现。它使用相同的算法,尽管修改了调用它的原始列表

我认为您的反向算法是正确的,但remain是局部变量,返回后无效,因此L4将包含无效指针。将reverse()的签名更改为take并返回List *

List*reverse(List*L){如果(L->next==NULL)返回L;List*remain=反向(L->next);List*current=保留;while(current->next!=NULL)current=(current->next);L->next=NULL;当前->下一个=L;//打印(保留);返回保留;}

只需查看reverse()函数,就可以在堆栈上创建一个名为remain的对象,并将其插入到列表中。这不起作用:一旦你从函数返回,这个对象就会超出范围(main()中的原始对象也有同样的问题,但你离开main()后就没有尝试使用它们)。此外,您的reverse()函数似乎具有二次型性能,而它应该是线性的。我认为这样的东西会起作用:

List* reverse(List* head) {
    List* tail(0);
    while (head) {
        List* tmp(head);
        head = head->next;
        tmp->next = tail;
        tail = tmp;
    }
    return tail;
}

上述实现也避免了递归。