有人可以帮我处理这个链表吗? 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();

}

您对

有疑问
  1. PrintAll 其中 Head 保持不变并使其无限循环。
  2. 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;
}

与第一个问题类似,循环条件是truefalse,但它永远不会改变,即循环永远不会运行或无限。

由于这似乎是一个练习,我会把它留给你来修复代码。

对于初学者来说,这个在全局命名空间中的声明

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