有人可以帮我处理这个链表吗? C++
Can someone help me with this linked list? C++
我明天有一个面向对象的考试,但我仍然被链表困住了。出于某种原因,我不太明白它们是如何工作的或如何正确实施它们。我看过很多视频和教程,但它仍然很复杂。我总是收到一个错误,它不会向控制台打印任何内容,只是一个空白的黑页。有人可以告诉他们我做错了什么吗?
谢谢。
#include <iostream>
#include <string>
using namespace std;
struct node
{
string name;
int number;
node* next;
};
struct node* head = 0;
class Employees
{
private:
node* head, * tail;
public:
Employees()
{
head = NULL;
tail = NULL;
}
void addToList(string Name, int Num)
{
node* n = new node;
n->name = Name;
n->number = Num;
n->next = NULL;
if (head == NULL)
{
head = n;
tail = n;
}
else
{
tail->next = n;
tail = tail->next;
}
}
void PrintAll()
{
while (head != NULL)
{
node* current;
while (current != NULL)
{
cout << current->name << "\t";
cout << current->number;
}
}
}
};
int main()
{
Employees a;
a.addToList("Robert", 54);
a.addToList("Manny", 77);
a.PrintAll();
}
您对
有疑问
PrintAll
其中 Head
保持不变并使其无限循环。
current
未初始化并且作为指针访问它是 UB
下面的代码片段应该可以解决您的问题,
void PrintAll()
{
node* temp = head;
while (temp != nullptr)
{
std::cout << temp ->name << "\t";
std::cout << temp ->number;
temp = temp->next
}
}
您的代码的主要问题是您的 PrintAll
方法编写不正确,并且您从未更新 current
指针。也许您还没有学过 for
循环,但这是他们的理想情况:
for(node* current = head; current != NULL; current = current->next) {
cout << current->name << "\t" << current->number;
}
for 循环的第一部分初始化变量(您在代码中忽略了这一点),接下来是结束条件(如您在 while
循环中所见),然后第三部分在循环的每个循环中更新变量,从而从头到尾遍历循环。
您可以使用 while
循环完成所有这些操作,但它表达您的意图不太清楚,因此应该首选 for
循环。我也不确定为什么你有一个 while
循环检查 head
是否为空?由于它在循环期间不会改变,因此无需重复检查它,并且 - 在任何情况下 - 单独检查它与简单地检查 current
一旦初始化为 [= 相比没有任何优势18=].
需要注意的是,如果您使用的是现代 C++ 版本,nullptr
应该优于 NULL
。
三期:
while (head != NULL)
{
/*...*/
}
您不在循环内修改 head
(您为什么要这样做),因此该循环将 运行 永远不会或永远。
第二个:
node* current;
while (current != NULL)
current
未初始化。将它与 NULL
进行比较会调用未定义的行为。总是初始化你的变量!
最后一个:
while (current != NULL)
{
cout << current->name << "\t";
cout << current->number;
}
与第一个问题类似,循环条件是true
或false
,但它永远不会改变,即循环永远不会运行或无限。
由于这似乎是一个练习,我会把它留给你来修复代码。
对于初学者来说,这个在全局命名空间中的声明
struct node
{
string name;
int number;
node* next;
};
struct node* head = 0;
^^^^^^^^^^^^^^^^^^^^^
是多余的,没有用处。删除它。
最好使结构节点成为class Employees 的内部成员。例如
class Employees
{
private:
struct node
{
string name;
int number;
node* next;
} *head = nullptr, *tail = nullptr;
//...
构造函数没有做任何特别的事情。所以可以定义为默认构造函数。
Employees() = default;
函数 addToList
应该通过常量引用接受第一个参数
void addToList( const string &Name, int Num )
^^^^^^^^^^^^^^^^^^
函数PrintAll
当指针头不是空指针时会死循环
void PrintAll()
{
while (head != NULL)
{
//...
}
}
而且它会调用未定义的行为,因为使用的指针当前未初始化
node* current;
while (current != NULL)
该函数应使用限定符 const 声明,因为它不会更改列表本身。
您还需要一个析构函数来释放为节点动态分配的内存。您也可以禁止复制构造和赋值。
这是一个演示程序,展示了如何实现 class。
#include <iostream>
#include <string>
using namespace std;
class Employees
{
private:
struct node
{
string name;
int number;
node* next;
} *head = nullptr, *tail = nullptr;
public:
Employees() = default;
~Employees()
{
while ( head != nullptr )
{
node *tmp = head;
head = head->next;
delete tmp;
}
tail = nullptr;
}
Employees( const Employees & ) = delete;
Employees & operator =( const Employees & ) = delete;
void addToList( const string &Name, int Num )
{
node *n = new node { Name, Num, nullptr };
if ( head == nullptr )
{
head = n;
tail = n;
}
else
{
tail->next = n;
tail = tail->next;
}
}
void PrintAll() const
{
for ( node *current = head; current != nullptr; current = current->next )
{
cout << current->name << ' ';
cout << current->number << '\t';
}
}
};
int main()
{
Employees a;
a.addToList( "Robert", 54 );
a.addToList( "Manny", 77 );
a.PrintAll();
cout << endl;
}
程序输出为
Robert 54 Manny 77
我明天有一个面向对象的考试,但我仍然被链表困住了。出于某种原因,我不太明白它们是如何工作的或如何正确实施它们。我看过很多视频和教程,但它仍然很复杂。我总是收到一个错误,它不会向控制台打印任何内容,只是一个空白的黑页。有人可以告诉他们我做错了什么吗? 谢谢。
#include <iostream>
#include <string>
using namespace std;
struct node
{
string name;
int number;
node* next;
};
struct node* head = 0;
class Employees
{
private:
node* head, * tail;
public:
Employees()
{
head = NULL;
tail = NULL;
}
void addToList(string Name, int Num)
{
node* n = new node;
n->name = Name;
n->number = Num;
n->next = NULL;
if (head == NULL)
{
head = n;
tail = n;
}
else
{
tail->next = n;
tail = tail->next;
}
}
void PrintAll()
{
while (head != NULL)
{
node* current;
while (current != NULL)
{
cout << current->name << "\t";
cout << current->number;
}
}
}
};
int main()
{
Employees a;
a.addToList("Robert", 54);
a.addToList("Manny", 77);
a.PrintAll();
}
您对
有疑问PrintAll
其中Head
保持不变并使其无限循环。current
未初始化并且作为指针访问它是 UB
下面的代码片段应该可以解决您的问题,
void PrintAll()
{
node* temp = head;
while (temp != nullptr)
{
std::cout << temp ->name << "\t";
std::cout << temp ->number;
temp = temp->next
}
}
您的代码的主要问题是您的 PrintAll
方法编写不正确,并且您从未更新 current
指针。也许您还没有学过 for
循环,但这是他们的理想情况:
for(node* current = head; current != NULL; current = current->next) {
cout << current->name << "\t" << current->number;
}
for 循环的第一部分初始化变量(您在代码中忽略了这一点),接下来是结束条件(如您在 while
循环中所见),然后第三部分在循环的每个循环中更新变量,从而从头到尾遍历循环。
您可以使用 while
循环完成所有这些操作,但它表达您的意图不太清楚,因此应该首选 for
循环。我也不确定为什么你有一个 while
循环检查 head
是否为空?由于它在循环期间不会改变,因此无需重复检查它,并且 - 在任何情况下 - 单独检查它与简单地检查 current
一旦初始化为 [= 相比没有任何优势18=].
需要注意的是,如果您使用的是现代 C++ 版本,nullptr
应该优于 NULL
。
三期:
while (head != NULL)
{
/*...*/
}
您不在循环内修改 head
(您为什么要这样做),因此该循环将 运行 永远不会或永远。
第二个:
node* current;
while (current != NULL)
current
未初始化。将它与 NULL
进行比较会调用未定义的行为。总是初始化你的变量!
最后一个:
while (current != NULL)
{
cout << current->name << "\t";
cout << current->number;
}
与第一个问题类似,循环条件是true
或false
,但它永远不会改变,即循环永远不会运行或无限。
由于这似乎是一个练习,我会把它留给你来修复代码。
对于初学者来说,这个在全局命名空间中的声明
struct node
{
string name;
int number;
node* next;
};
struct node* head = 0;
^^^^^^^^^^^^^^^^^^^^^
是多余的,没有用处。删除它。
最好使结构节点成为class Employees 的内部成员。例如
class Employees
{
private:
struct node
{
string name;
int number;
node* next;
} *head = nullptr, *tail = nullptr;
//...
构造函数没有做任何特别的事情。所以可以定义为默认构造函数。
Employees() = default;
函数 addToList
应该通过常量引用接受第一个参数
void addToList( const string &Name, int Num )
^^^^^^^^^^^^^^^^^^
函数PrintAll
当指针头不是空指针时会死循环
void PrintAll()
{
while (head != NULL)
{
//...
}
}
而且它会调用未定义的行为,因为使用的指针当前未初始化
node* current;
while (current != NULL)
该函数应使用限定符 const 声明,因为它不会更改列表本身。
您还需要一个析构函数来释放为节点动态分配的内存。您也可以禁止复制构造和赋值。
这是一个演示程序,展示了如何实现 class。
#include <iostream>
#include <string>
using namespace std;
class Employees
{
private:
struct node
{
string name;
int number;
node* next;
} *head = nullptr, *tail = nullptr;
public:
Employees() = default;
~Employees()
{
while ( head != nullptr )
{
node *tmp = head;
head = head->next;
delete tmp;
}
tail = nullptr;
}
Employees( const Employees & ) = delete;
Employees & operator =( const Employees & ) = delete;
void addToList( const string &Name, int Num )
{
node *n = new node { Name, Num, nullptr };
if ( head == nullptr )
{
head = n;
tail = n;
}
else
{
tail->next = n;
tail = tail->next;
}
}
void PrintAll() const
{
for ( node *current = head; current != nullptr; current = current->next )
{
cout << current->name << ' ';
cout << current->number << '\t';
}
}
};
int main()
{
Employees a;
a.addToList( "Robert", 54 );
a.addToList( "Manny", 77 );
a.PrintAll();
cout << endl;
}
程序输出为
Robert 54 Manny 77