【问题标题】:C++ delete element function in a doubly linked listC++删除双向链表中的元素函数
【发布时间】:2014-03-04 13:23:58
【问题描述】:

我对 C++ 和它的数据结构相当陌生。我为我的双向链表类创建了一些函数,但我在删除函数中遇到了麻烦。我创建了一个 deleteHead() 函数,它删除列表中的第一个节点,一个 deleteTail() 函数,它删除列表中的最后一个节点,最后一个 deleteElement(Item) 函数遍历列表并删除具有那里面的Item。

问题是每当我尝试从列表中删除唯一剩余的节点时,程序就会崩溃。即如果我插入一个节点,然后我在同一个节点上调用 deleteElement 函数(如果我插入的节点是列表中唯一的节点)程序崩溃。

这是我的代码。

template <class T>
void LinkedList<T>::deleteElement(T item)
{
    ListItem<T>* current = head;
    ListItem<T>* temp;
    if (head == NULL) {                         // if list is empty end the function
        return;
    }
    while (current) {
        if (current->value == item) {
            if (current == head) {              // if item is in the head
                deleteHead();
            }
            else if (current == getTail()) {    // if item is in the tail
                deleteTail();
            }
            // if item is between two nodes
            else if (current != head && current != getTail()) { 
                temp = current;
                temp->prev->next = temp->next;
                temp->next->prev = temp->prev;
                current->next = NULL;
                current->prev = NULL;
                if (current->next == NULL) {
                    deleteTail();
                }
            }
        }
        current = current->next;
    }
}

// Delete the Head Node
template <class T>
void LinkedList<T>::deleteHead()
{
    if (head != NULL) { // as long as head is not null, delete head
        ListItem<T> *current = head;
        head = head->next;
        current->next = NULL;
        head->prev = NULL;
    } else {return;} // if head is null, end the function without doing anything
}

// Delete Tail Node
template <class T>
void LinkedList<T>::deleteTail()
{
    ListItem<T> *tail = getTail();
    tail = tail->prev;
    tail->next->prev = NULL;
    tail->next = NULL;
}

【问题讨论】:

  • 您是否尝试过调试您的代码?
  • 很可能在deleteHead() 中使用head = head-&gt;next;,如果列表只包含一个元素,则必须是NULL,在这种情况下head-&gt;prev = NULL; 会崩溃。

标签: c++ doubly-linked-list


【解决方案1】:

您的代码中有几个问题。首先,您在访问它们之前不会检查任何指针。例如,这里:

temp = current;
temp->prev->next = temp->next;
temp->next->prev = temp->prev;

如果列表中只有一个元素,则其nextprev 成员可能为空。这意味着尝试将某些内容分配给 temp-&gt;prev-&gt;nexttemp-&gt;next-&gt;prev 将是访问冲突。

这同样适用于其他地方,包括 while 循环末尾的这一行:

current = current->next;

在那个阶段,current 可能已被删除,这意味着尝试访问其next 成员应该会失败。但由于另一个问题,它目前可能不会失败......

非常重要的是,您实际上并没有删除任何内容。 C++ 没有垃圾收集器,因此您不能只将原始指针设置为 null 并忘记它。您必须在其上调用delete 来销毁和释放对象,否则会导致内存泄漏。您需要在整个代码中修复它,然后可能会修改所有功能。您需要非常小心,不要在对象被删除后访问它。

话虽如此,您应该真正使用智能指针(即std::shared_ptr),而不是使用原始指针。当没有其他对象有指向它的指针时,它们会为您删除对象。您仍然需要避免访问已删除的对象,但它使编码更简单,并有望更现代/更强大。

【讨论】:

    【解决方案2】:

    建议:

    步骤#1 - 将成员变量ListItem&lt;T&gt;* tail 添加到类ListItem&lt;T&gt;

    第 2 步 - 将所有对 getTail() 的调用替换为 tail

    第 3 步 - 在函数 deleteElement 中,您可以替换:

    else if (current != head && current != tail)
    

    与:

    else
    

    步骤#4 - 在函数deleteElement,您应该替换:

    current->next = NULL;
    current->prev = NULL;
    if (current->next == NULL)
        deleteTail();
    

    与:

    delete current;
    

    步骤#5 - 重写函数deleteHead如下:

    ListItem<T>* current = head;
    if (head == tail)
        head = tail = NULL;
    else
        head = head->next;
    delete current;
    

    步骤#6 - 重写函数deleteTail如下:

    ListItem<T>* current = tail;
    if (tail == head)
        tail = head = NULL;
    else
        tail = tail->prev;
    delete current;
    

    【讨论】:

      【解决方案3】:

      答对了。这是我的数据结构作业中的一个问题。这是我实现的代码。是的,我知道它有冗余和低效率,但我必须在任务的框架内工作。

      这是我的 deleteElement() 函数:

      template <class T>
      void LinkedList<T>::deleteElement(T item)
      {
          ListItem<T>* current = head;
          ListItem<T>* temp;
          if (head == NULL) {                // if list is empty end the function
              return;
          }
          while (current) {
              if (current->value == item) {
                  if (current == head) {              // if item is in the head
                      deleteHead();
                  }
                  else if (current == getTail()) {    // if item is in the tail
                      deleteTail();
                  }
                  else if (current != head && current != getTail()) { 
                  // if item is between two nodes
                      temp = current;
                      temp->prev->next = temp->next;
                      temp->next->prev = temp->prev;
                      current->next = NULL;
                      current->prev = NULL;
                      if (current->next == NULL) {
                          deleteTail();
                      }
                  }
              }
              current = current->next;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-06-11
        • 1970-01-01
        • 1970-01-01
        • 2021-11-22
        • 2016-07-06
        • 2020-12-18
        • 2021-04-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多