我有一个构造函数,析构函数,一个返回链表顶部的函数。我不确定createNode函数,也无法弄清楚如何执行addNode函数。
//构造函数
LinkedList::LinkedList()
{
head = NULL;
}
//析构函数
LinkedList::~LinkedList()
{
struct Node *temp = head;
int nodeCount = 0;
struct Node *nextNode;
while (temp != NULL)
{
nextNode = temp->next;
delete temp;
nodeCount++;
temp = nextNode;
}
head = NULL;
cout << "The number of deleted nodes is: " << nodeCount << "\n";
}
//此函数返回链接列表的标题
Node *LinkedList::getHead()
{
return head;
}
///此函数使用给定的参数info创建一个新节点。它返回一个指向新创建的节点的指针。
Node * LinkedList::createNode(string name, int winScore, int loseScore)
{
Node *temp = new Node;
temp->name = name;
temp->winScore = winScore;
temp->loseScore = loseScore;
temp->next = NULL;
return new Node; // I think I have done this function right but please correct me if I'm wrong
}
//该函数首先调用createnode。然后,按字母顺序将新创建的节点插入到链表中。它还返回一个指针 指向新添加的节点。
Node *LinkedList::addNode(string name, int winScore, int loseScore)
{
//add code here which I couldn't do
}
答案 0 :(得分:0)
链接列表有些通用。通过简单的实现,您可以为列表创建一个类实例,构造函数只需要将列表的第一个节点(head
)设置为NULL
。 (您可以使构造函数重载以获取字符数据并调用insert
)
从数据结构(或类,选择)开始:
struct node_t { /* simple struct holding char and next pointer */
char data;
node_t *next;
};
insert
函数始终为新节点创建并分配存储,并初始化next
指针NULL
,例如
class linkedlist {
node_t *head, *iter; /* private members */
public:
linkedlist() { /* constructor - sets head NULL */
head = NULL;
}
...
node_t *insert (char data) {
node_t *node = new node_t; /* allocate new node */
node->data = data; /* set node data */
node->next = NULL;
...
此时,在insert
中,所有剩下的工作就是检查是否head == NULL
,如果是,您就知道这是您的第一个节点,因此只需设置head = node;
,例如
if (!head) /* if 1st node */
head = node;
如果head != NULL
,那么您就需要设置iter = head;
并遍历列表端以设置last->next = node;
。您可以通过简单的while
循环来完成此操作,例如
else { /* otherwise */
iter = head;
while (iter->next) /* traditional iterate to find last */
iter = iter->next;
iter->next = node; /* set new last */
}
除了返回指向node
的指针外,基本上就是其他的东西。但是,如果您保留last
指针,并且始终在last = node;
函数的末尾设置insert
,则无需重复查找最后一个节点,只需设置{ {1}},而不是迭代然后更新last->next = node;
一个简短的例子可以帮助您:
last = node;
使用/输出示例
#include <iostream>
#include <string>
using namespace std;
struct node_t { /* simple struct holding char and next pointer */
char data;
node_t *next;
};
class linkedlist {
node_t *head, *iter; /* private members */
public:
linkedlist() { /* constructor - sets head NULL */
head = NULL;
}
~linkedlist() { /* destructor - free list memory */
iter = head;
while (iter) {
node_t *victim = iter;
iter = iter->next;
delete victim;
}
}
node_t *insert (char data) {
node_t *node = new node_t; /* allocate new node */
node->data = data; /* set node data */
node->next = NULL;
if (!head) /* if 1st node */
head = node;
else { /* otherwise */
iter = head;
while (iter->next) /* traditional iterate to find last */
iter = iter->next;
iter->next = node; /* set new last */
}
return node; /* return node */
}
void print (void) { /* simple print function */
iter = head;
while (iter) {
cout << iter->data;
iter = iter->next;
}
cout << '\n';
}
};
int main (void) {
string s = "my dog has fleas";
linkedlist l;
for (auto& c : s)
l.insert(c);
l.print();
}
内存使用/错误检查
始终使用内存/错误检查程序来验证您对分配的操作没有做任何奇怪的事情,并确认您已释放分配的所有内存。对于Linux,通常选择$ ./bin/ll_insert
my dog has fleas
。只需通过它运行程序即可:
valgrind
仔细检查一下,如果还有其他问题,请告诉我。我将$ valgrind ./bin/ll_insert
==9240== Memcheck, a memory error detector
==9240== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9240== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==9240== Command: ./bin/ll_insert
==9240==
my dog has fleas
==9240==
==9240== HEAP SUMMARY:
==9240== in use at exit: 0 bytes in 0 blocks
==9240== total heap usage: 18 allocs, 18 frees, 73,001 bytes allocated
==9240==
==9240== All heap blocks were freed -- no leaks are possible
==9240==
==9240== For counts of detected and suppressed errors, rerun with: -v
==9240== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
指针的实现留给您。
添加单独的last
节点功能
您可以灵活地决定如何将代码分解为单独的函数。 create
函数通常只处理分配给create
并设置node
的值并将data
初始化为next
。我不确定在这里使事情变得更容易的多少,但是在您拥有复杂的NULL
函数的地方,确实可以帮助整理create
函数。
在这里,您只需将调用移至insert
并分配给new
和data
到新的next
函数,然后在{的顶部调用create
{1}},例如
create
在功能上与在insert
中完成所有操作相同(并且智能编译器也可能会对其进行相同的优化)。因此,完全由您自己决定是什么使它更易于理解。