删除链接列表中的后退元素

时间:2013-10-11 19:44:08

标签: c++ linked-list dynamic-memory-allocation

这与具有类似名称的问题不重复,这涉及OOP以及新呼叫和删除呼叫。

我正在尝试编写一个函数,它将迭代到我的链表的后面,然后删除最后一个节点的堆中分配的内存。

这是我的代码:

void LinkedList::delete_back(){
    if(head != NULL){
            ListNode *end = head;
            while(end->next != NULL)
                    end = end->next;
            delete end;
    }
    size--;
}

这是我的班级定义:

class ListNode{

    public:
            Item data;
            ListNode *next;
};
class LinkedList{

    private:
            ListNode *head;
            int size;

    public:
            LinkedList();
            ~LinkedList(); 
            bool empty();
            void insert_front(Item i);
            void insert_back(Item i);
            void delete_front();
            void delete_back();
            void print();
};

Annddddd .....这是问题所在,我收到了来自valgrind的错误消息垃圾邮件,一些说明无效读取大小4,其他说明无效读取大小8:

==4385== Invalid read of size 4
==4385==    at 0x400CAA: LinkedList::print() (in /home/jon/jball2_lab06/linkedlist)
==4385==    by 0x400EDD: main (in /home/jon/jball2_lab06/linkedlist)
==4385==  Address 0x5a04f30 is 0 bytes inside a block of size 16 free'd
==4385==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4385==    by 0x400C5E: LinkedList::delete_back() (in /home/jon/jball2_lab06/linkedlist)
==4385==    by 0x400E99: main (in /home/jon/jball2_lab06/linkedlist) 

如果有帮助我会发布其余的错误,但除非我需要,否则我不想在50行上打4次。有谁知道这可能是什么?我做错了什么?

UPDATE ----------------------- 我已将代码编辑为:

void LinkedList::delete_back(){
    if(head != NULL){
            ListNode *end = head;
            ListNode *prev_end;
            while(end->next != NULL){
                    prev_end = end;
                    end = end->next;
            }
            prev_end->next = NULL;
            if(end != NULL) delete end;
            size--;
    }
}

我现在收到更多关于8/4大小错误和无效/删除错误的无效读取

==5294== Invalid free() / delete / delete[] / realloc()
==5294==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

和此:

==5294== Use of uninitialised value of size 8
==5294==    at 0x400C3D: LinkedList::delete_back() (in /home/jon/jball2_lab06/linkedlist)
==5294==    by 0x400EEC: main (in /home/jon/jball2_lab06/linkedlist)

以下是使用的测试代码:

    for(Item i = 50; i < 100; i++){
            ll.insert_back(i);
            cout << "Inserted [" << i << "] in back.\n";
    }
    ll.print();
    for(int i = 0; i < 50; i++)
            ll.delete_back();
    cout << "Removed 50 elements from the back.\n";
    ll.print();

使用delete_back()

从列表中删除最后一个元素时会发生这种情况

UPDATE -------------------------

问题在于,如果end-&gt; next为null,而while循环将永远不会执行,则prev_end将永远不会被初始化。发布了已实施修复的答案。

6 个答案:

答案 0 :(得分:4)

如果列表中包含至少2个节点,则delete表示最后一个节点。前一个仍然引用了最后一个(不再存在),在print尝试取消引用无效(悬空)指针时导致未定义行为。而不是:

ListNode *end = head;
while(end->next != NULL)
    end = end->next;
delete end;

你应该这样做:

if (head->next == NULL) {
    delete head;
    head = NULL;
}
else {
    ListNode *nextToEnd = head;
    ListNode *end = head->next;
    while (end->next != NULL) {
        nextToEnd = end;
        end = end->next;
    }
    delete end;
    nextToEnd->next = NULL;
}

答案 1 :(得分:1)

不要忘记更新新的最后一个元素的next

void LinkedList::delete_back(){
    if(head != NULL){
            ListNode *end = head;
            ListNode *prev_end;
            while(end->next != NULL)
            {
                 prev_end = end;
                 end = end->next;
            }
            prev_end->next = 0;
            delete end;
    }

此外,如果清空列表,请将head设置为NULL。

答案 2 :(得分:1)

您没有将新的结束节点设置为null。

例如:

  

A-&GT; B-&GT; C-&GT; NULL

删除C时,B的下一个是悬空指针

因此,在delete函数中,您需要转到倒数第二个节点,并将其下一个节点设置为NULL。

在删除C后的上述示例中,列表应如下所示

  

A-> B-> NULL而不是A-> B->(悬空)

所以你可以在下一个delete_back操作中删除B.

您可以执行以下操作

void LinkedList::delete_back(){
if(head != NULL){
        ListNode *end = head;
        //This if block is for when only one element is left
        if(end->next == NULL)
         { delete end;
           end = NULL;
         }
        else
        while(end!= NULL)
        { 
               if(end->next) /// reach the second last element
                if(end->next->next==NULL)
                 {
                  delete end->next; //delete the last element
                  end->next=NULL; // set the next of second last element to NULL
                 }
               end=end->next;
        } 
  size--;
  }
  }

答案 3 :(得分:0)

修正了所有问题。

代码:

void LinkedList::delete_back(){
    if(head != NULL){
            ListNode *end = head;
            if(end->next != NULL){
                    ListNode *prev_end;
                    while(end->next != NULL){
                            prev_end = end;
                            end = end->next;
                    }
                    prev_end->next = NULL;
                    delete end;
            }
            else {
                    delete head;
                    head = NULL;
            }
            size--;
    }
}

答案 4 :(得分:0)

像这样应该工作

void del_rear()

{
  struct node *end, *last

 if (head->next != NULL) {

   *end=head;

while(end->next!=null){
*last=end;
 end=end->next;
  }
    free(end);
    last->next=null;
   }     
 else
   {

    pf("list is empty\n");
 }
} 

答案 5 :(得分:0)

最简单的删除代码是:

void DeleteAtLast(){
    node *temp=head;
    while(temp->next->next!=NULL){
        temp=temp->next;
    }
    temp-next=NULL;
}