链表追加到尾部

Linked Lists Append To Tail

本文关键字:尾部 追加 链表      更新时间:2023-10-16

我正在尝试创建一个 appendToTail 函数,它将在单向链表的末尾添加一个节点。

如果头部为 NULL(链表为空),我在添加节点时遇到问题

class Node {
private:
Node* next;
int data;
public:
Node(int d, Node* n = NULL)
: data(d)
, next(n)
{
}
void appendToTail(int);
//other trivial functions(getters and setters etc. ) defined and
//declared
};
void Node::appendToTail(int d)
{
Node* end = new Node(d);
Node* n = this;
if (n == NULL)
n = end;
else {
while (n->next != NULL)
n = n->next;
n->next = end;
n->next->next = NULL;
}
end = NULL;
delete end;
}
int main()
{
Node* n = NULL;
n->appendToTail(5);
std::cout << n->getData(); //getData() is a function which
//retrieves the Data member variable
}

我期望得到 5,但我收到一个错误,这似乎是因为我的节点保持空值造成的。

现在使用现代C++习语,我们使用智能指针而不是原始指针,它为您提供了 RAII(资源获取即初始化)机制的好处。此外,如果你想要一个优雅的问题解决方案,你应该引入一个List类,你可以用它更清楚地表达空列表的概念。它会给出这样的东西:

#include <memory>
#include <iostream>
class List
{
public:
class Node
{
private:
std::shared_ptr<Node> next;
int data;
public: 
Node(int d):next(nullptr),data(d){}
inline int getData() const {return data;}
inline std::shared_ptr<Node> getNext() const {return next;}
friend List;
};
List():head(nullptr),tail(nullptr){}
void appendToTail(int );
inline std::shared_ptr<Node> getHead() const {return head;}
inline std::shared_ptr<Node> getTail() const {return tail;}
private:
std::shared_ptr<Node>   head;
std::shared_ptr<Node>   tail;
};
void List::appendToTail(int d)
{
auto newTail = std::make_shared<Node>(d);
if (head == nullptr)
{
head = tail = newTail;
}
else
{
tail->next = newTail;
tail = newTail;
}
}
int main()
{
List    l;
l.appendToTail(5);
std::cout<<l.getHead()->getData();
}

但是你绝对应该更喜欢std::list<T>std::vector<T>.

不幸的是,您的方法存在一些错误。语义错误和对链表的解释的逻辑错误。让我们从你最初的误解开始。不能向空列表添加新尾部。因为它是 emtpy。意思,还不存在。仅当某个对象存在/实例化时,您才能添加尾巴。您不能向不存在的内容添加某些内容。因此,您从 Node* n = nullptr 开始的想法在逻辑上是行不通的。

此外,您正在取消引用 nullptr(主要错误)。这也是代码的主要问题。什么都没用。您需要一个实例化的对象,然后才能调用它的成员函数。

因此,在填充列表之前,您需要先创建/实例化它。所以你需要在你的主函数中显式创建第一个节点

Node* n = new Node (5)

然后列表是存在的,从现在开始,您可以通过调用 appendToTail 来添加新成员。

您的代码中有更多的语义错误,幸运的是没有副作用。

不得删除函数中的"end"变量。您希望为新尾部保留新分配的内存。但是,通过将"end"设置为nullptr,然后调用删除,引入了额外的语义错误。删除 nullptr 是一个 noOp,不会执行任何操作。因此,尽管您有语义错误,但这不会造成任何麻烦。

还有更多:

对于指向 Null 的指针,应始终使用 nullptr。

而且,你的

if (n == NULL)

总是假的。在此之前,您将其分配给 n。这永远不会为空。您可以删除 if else。保留其他语句,除了

n->next->next = NULL;

那没必要。构造函数已经为您做到了这一点。如前所述,接下来的 2 个语句也应该被消除。

此外,您可能想阅读更多有关链表概念的信息。

我希望我能帮上一点忙