链表追加到尾部
Linked Lists Append To Tail
我正在尝试创建一个 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 个语句也应该被消除。
此外,您可能想阅读更多有关链表概念的信息。
我希望我能帮上一点忙
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 将尾部调用void(i32,..)位转换为llvm::函数以获取FnAttribute
- basic_string的前导/尾部不区分空格的特征
- 如何在特定位置追加 json 文件
- 在带有尾部斜杠的路径上返回 std::filesystem::create_directories() 的值
- 编写一个函数来删除单链表中的节点(尾部除外),仅授予对该节点的访问权限
- 使用 swig 追加到字节数组
- 如何在不使用追加函数的情况下追加到字符串C++?
- 如何在运行时在对象数组中动态追加新对象C++并打印它们
- 了解 cin.fail() 和 cin.clear语言 - Vector 追加程序
- 文件追加的方式是,它在每次保存C++后结束行
- 追加位以增加字符的大小
- 在 c++ 中打开文件、删除标点符号并追加到另一个文件中
- 使用 sprintf 追加到字符数组
- 如何在Qt中合并/追加/添加两个用于线程的模型?
- 问:Apache Arrow 数组生成器不安全追加
- 字符串的异常行为会追加属性 C++
- 将数据追加到C++中的数组
- 附加作为空字符串的 ostream 可防止进一步追加
- 链表追加到尾部