【问题标题】:Simple Linked List Implementation in C++C++ 中的简单链表实现
【发布时间】:2010-02-17 02:22:01
【问题描述】:

我是我的第一个 C++ 课程的编程学生,最近我们介绍了链表,我们被分配了一个任务来实现一个简单的链表。除了pop_back() 函数之外,我已经编写了所有代码,该函数应该返回指向Node 的指针,该指针需要在Main() 中删除。否 Node 删除是在实际功能中完成的。所以我的问题是:

您愿意帮助我为我的pop_back() 功能指明正确的方向吗?另外,如果您发现我做错了什么,请告诉我。

另外,这个链表只适用于字符串。在这种情况下,是一个购物清单,所以一个字符串表示项目的数量(1,2),一个字符串表示项目类型。 (牛奶、鸡蛋等)

下面我包含了我的 List 和 Node 类实现,因此您可以了解我到目前为止所做的工作。

Node.cpp

Node::Node(void)
{
    descrip = " ";
    quantity = " ";
    previous = NULL;
    next = NULL;
}
Node::Node(string q, string d)
{
    descrip = d;
    quantity = q;
    previous = NULL;
    next = NULL;
}
Node* Node::GetNext()
{
    return next;
}
Node* Node::GetPrevious()
{
    return previous;
}
void Node::SetNext(Node * setter)
{
    next = setter;
}
void Node::SetPrevious(Node * setter)
{
    previous = setter;
}

List.cpp

List::List(void)
{
   first = NULL;
   last = NULL;
   numNodes = 0;
}
Node* List::GetFirst()
{
    return first;
}
Node* List::GetLast()
{
    return last;
}
void List::SetFirst(Node* setter)
{
    first = setter;
}
void List::SetLast(Node* setter)
{
    last = setter;
}
int List::GetNumNodes()
{
    return numNodes;
}
void List::push_front(Node* item)
{
   if (first == NULL)
   {
       first = item;
       last = item;
   }
   else 
   {
       Node* pFirst = first;
       item->SetNext(pFirst);
       first = item;
       numNodes++;
   }
}
void List::push_back(Node * item)
{
    if (last == NULL)
    {
       first = item;
       last = item;
    }
    else 
    {
        last->SetNext(item);
        last = item;
        numNodes++;
    }
}
Node* List::pop_front()
{
    Node* temp = first;
    first = first->GetNext();
    if (first == NULL)
    {
        temp = first->GetNext();
        first = p;
    }
    if (first == NULL)
    {
        last = NULL;
    }
    if (numNodes > 0)
    {
        numNodes--;
    }
    return temp;
}
Node* List::pop_back() // this whole function may be wrong, this is just my attempt at it
{
    Node* temp;
    temp = first;

    while((temp->GetNext()) != NULL)
        // im stuck here

}

【问题讨论】:

    标签: c++ pointers linked-list


    【解决方案1】:

    一些提示:

    0x1243bfa3
    0x45afc56e
    0xdeadbeef
    

    更多指点:

    1. 您应该更喜欢在初始化列表中初始化您的类成员,而不是在构造函数的主体中。

    2. 在 C++ 中,与 C89 不同,我们将不带参数的函数声明和定义为 void f();,而不是 void f(void);

    3. 在 C++ 中,我们通常使用 0 重置指针,而不是 NULL

      请参阅下文了解我在代码中的含义。

    4. 优秀的 C++ 代码会尝试利用 RAII。这意味着在很大程度上避免使用原始指针。在这种情况下,普通的旧 std::auto_ptr<> 可以完全替代原始的 Node* 指针。但是,我确实认为这里的部分练习是指针算术,所以我只是把它作为一个旁注。

    5. 如果您附上类声明,这对我们很有用。我假设所有这些访问器和修改器,GetFirst()SetFirst() 等都在那里,因为它们是公开的。这是个坏主意。首先,它们暴露了私有指针,这破坏了访问器的全部意义。其次,它们没有做任何特别的事情,所以它们只是额外的代码——这意味着有额外的错误空间。这就引出了下一点。

    6. 您的变异器不正确。您盲目地为私有成员指针分配一个新值,而没有删除您之前拥有的值。那是内存泄漏。

    7. 在列表为空时尝试过pop_front()

    8. 最后,8 是一个整数,是时候解决手头的问题了。 pop_back()。我的问题是,如果您如此细致地维护指向列表最后一个节点的指针,为什么还要一直遍历列表呢?实际上,如果您不想维护指向列表末尾的指针,那么您必须一直遍历到最后一个节点才能弹出它。为此,您的方向是正确的。除了...

    9. 当您通过指针访问成员时,如在first->GetNext() 中,始终确保 first 不是空指针 - 否则在函数的文档注释中声明您假定指针不为空。

    这些应该可以帮助您入门。

    代码中的第 1、2 和 3 点:

    Node::Node()
    : descrip(" "), quantity(" "), previous(0), next(0)
    {
    }
    

    【讨论】:

    • 顺便说一句,对于任何在 2011 年之后看到这一点的人,C++ 程序员在能够使用 C++11 时,更喜欢 nullptr 而不是 NULL0
    【解决方案2】:

    所以如果我理解这一点,你只想遍历你的链表,直到你到达链表中的最后一个节点并返回指向它的指针? 我很确定除了

    Node* List::pop_back() // this whole function may be wrong, this is just my attempt at it  
    {  
        Node* temp;  
        temp = first;  
        while(temp->GetNext() != NULL)  
        {  
            temp = temp->GetNext();  
        }  
        return temp;  
    }
    

    所以如果我没看错的话,它会不断循环,直到它到达后面一行没有的节点,然后返回它。

    【讨论】:

    • 在编辑器中突出显示代码部分并按下“代码”格式按钮——它看起来像一个由 1 和 0 组成的小方块。
    • 啊哈!这是有道理的!让我自己去试一下,画几张图。那我就回来吧。
    • 你也可以while((temp = temp->GetNext()) != NULL){} 但我不确定...我现在有点空白
    • 但是,您可能只想到 temp->GetNext() == 最后。然后,您可以返回最后一项,并将倒数第二个元素更改为最后一个元素并将其 next 设置为 NULL。无论如何,您已经存储了最后一个元素。
    • 我在回答中问过,如果您已经有一个指向该元素的指针,为什么要一直走到列表的末尾。但除此之外,@Craig,你建议while( (temp = temp->GetNext()) != NULL ),但你假设列表至少有一个元素。那是因为您取消引用 temp 指针。您必须清楚这一假设并明确说明,无论是在带有assert() 的代码中还是在 cmets 中。
    【解决方案3】:

    我喜欢之前发帖者的回答,但您可能要记住的一件事是,如果您有一个空列表。然后您的第一个指针将等于 NULL,您将尝试调用 NULL->GetNext() 和 Seg Fault。我想你可以稍微编辑一下上面的代码,仍然让它像这样工作:

    Node* List::pop_back() 
    {  
        Node* temp;  
        temp = first;  
        while(temp != NULL && temp->GetNext() != NULL)  
        {  
            temp = temp->GetNext();  
        }  
        return temp;  
    }
    

    如果列表中没有任何内容并且仍然正常工作,这将使函数返回 NULL。

    【讨论】:

      【解决方案4】:

      如果你也发布了你的班级声明,那肯定会对我有所帮助。我不能保证以下内容是正确的,但对我来说很有意义

      Node* List::pop_back()
      {
        Node *temp = NULL;
        if(numNodes == 1) 
        {
          temp = first;
          // setting the list pointers to NULL
          first = NULL;
          // setting the list pointers to NULL 
          last = NULL; 
          //You should also probably remove the links from your node 
          //to the next and previous nodes but since you didn't specify 
          //this it is up to you
          numNodes--;
        }
        else if(numNodes > 1) //more than one element
        {
          //the pointer you want to return
          temp = last;
          //For clarity I am creating another variable here
          Node *newLast = temp->GetPrevious(); 
          //Setting the new last node to point at nothing so now temp 
          //is "disconnected from the list"
          newLast->next = NULL; 
          //the last pointer of the list is now pointing at the new last node
          last = newLast;         
      //You should also probably remove the links from your node 
      //to the next and previous nodes but since you didn't specify this it is up to you
              numNodes--; //decrement the counter
            }
            return temp;
          }
      

      【讨论】:

        猜你喜欢
        • 2011-09-17
        • 2019-05-17
        • 2015-08-18
        • 2013-12-03
        • 2020-09-18
        • 2014-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多