为什么链接列表的delete_last_element会删除第一个元素?

时间:2015-01-31 21:29:18

标签: c++ linked-list

我正在编写一个应该删除链表的最后一个元素的函数

这是我对节点的定义

struct Node {
  int key;
  Node* next;
  }; 

我有一个节点列表1,它为值1,2,3

运行插入函数3次

插入功能如下所示

void insert( Node*& head, int key) {
  Node * curr = new Node;
  curr->key  = key;
  curr->next = head;

  head = curr;
}

现在我的delete_last_element函数看起来像这样

void delete_last_element( Node*& head )
{


    Node  *curr;    
    if (head == NULL)
        return;

    curr = head->next; 
    if (curr == NULL){
        delete head;
        head = NULL;
        return;
    }
    head = curr;

      while (curr->next != NULL) {
        head = curr;
        curr = curr->next;
      }

      delete head->next;
      head -> next = NULL;


}

基本上我的想法是我首先会看到第一个元素是否为null,如果是,那么我什么都不做,因为没有最后一个元素。然后我将curr设置为head->接下来查看列表中的下一个元素,如果为null我将删除head,因为我知道它是最后一个元素并返回。

现在我知道第一个元素不是最后一个元素,我将头部分配给curr或第二个元素。从这里我进入while循环并检查下一个元素(从第3个开始)是否为null,如果是,我删除当前元素,如果不是,我移动到下一个元素,然后检查后面的元素。 / p>

现在我的链接列表最初以3 2 1开头,但无论出于何种原因,当我运行delete_last_element函数时,它变为2而不是3 2.

谁能告诉我自己可能做错了什么?

由于

3 个答案:

答案 0 :(得分:0)

在你的插入功能中,你总是设置在指向头部旁边:

curr->next = head;

最重要的是,你正在改变你的头脑,

head = curr;

这是链表中的最后一项。所以你实际上是在意外地向后制作链表。

要把它画出来,这就是你在做什么;向下箭头指向头部,箭头指向下一个方向

插入1:

|
v
1

插入2 :(您正在创建一个新节点:2,然后您正在创建它接下来是前一个头,即1,然后您将当前节点2设置为新头)

     |
     v
1 <- 2

插入3:

          | 
          v
1 <- 2 <- 3

答案 1 :(得分:0)

在这个例子中,基本上你需要注意两个条件:

  • 列表为空。
  • 列表中只有一个元素。

如果列表为空,则由指向head的{​​{1}}指针指示。如果没有列表,则无法删除任何内容,因此我们可以退出该功能:

nullptr

检查列表中是否只有一个元素的原因是有用的,如果我们保留两个遍历列表的指针 - 一个指向当前元素,一个指向当前元素。 &#34;之前&#34;在删除当前节点后,指针必须将其if (head == nullptr) return; 指针设置为next。如果没有上一个节点(因为只有一个元素),那么我们就不能使用前一个指针。

nullptr

现在我们必须遍历列表以找到最后一个元素。您不应该使用if (!head->next) { delete head; head = nullptr; return; } node *prev = nullptr, // previous is nullptr *curr = head; // start at head 来遍历列表,因为需要head来表示列表的开头,您不能将其指向其他位置,因此我们使用head代替

curr

现在我们已经到达列表的末尾,我们可以删除while (curr->next) { prev = curr; curr = curr->next; } 并将之前的指针curr设置为next

nullptr

就是这样。这是完整的方法:

delete curr;
prev->next = nullptr;

Here is a demo showing its use


了解上述代码后,您可以了解如何缩短代码。

void delete_last_element(node*& head)
{
    if (head == nullptr) // list is empty, nothing to do
        return;

     if (head->next == nullptr) // only one element in list
     {
         delete head;
         head = nullptr; // set back to nullptr
         return; // get outta here
     }

     node *prev = nullptr,
          *curr = head;

     while (curr->next)
     {
         prev = curr;
         curr = curr->next;
     }

     delete curr;
     prev->next = nullptr;
}

答案 2 :(得分:0)

递归在这里很有用。列表是:

  
      
  1.   
  2. 只有一个元素
  3.   
  4. 有多个元素
  5.   

我们按以下方式处理这三种情况:

void delete_last_element( Node*& head ) {
    if(head == NULL) {
         // The list is empty, nothing to remove.
         // Just do nothing and return
         return;
    }
    else if (head->next == NULL) {
         // This list has exactly one element.
         // Remove it and return
         delete head; // free the memory
         head = NULL; // the single-element list is now an empty list
         return;
    }
    else {
        // We have a list with more than one element.
        // Let's be lazy
        delete_last_element(head->next);
        return;
    }

依次处理这三个案件中的每一个案件。最后一种情况(“具有多个元素的列表”)仅通过调用delete_last_element(head->next);来处理。我们的想法是删除从head开始的5元素列表中的最后一个元素与删除以head->next开头的4元素列表完全相同。