删除链表中的 back 元素

Deleting the back element in a linked list

本文关键字:back 元素 链表 删除      更新时间:2023-10-16

这不是具有相似名称的问题的副本,这涉及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();
};

安德德.....这就是问题所在,我收到来自 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) 

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

更新-----------------------我已将代码编辑为:

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() 从列表中删除最后一个元素时,会发生这种情况

更新-------------------------

问题是,如果 end->next 为 null,则 while 循环将永远不会执行,则永远不会启动prev_end。 已发布的答案,并实施了修复程序。

当您的列表包含至少 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;
}

不要忘记更新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。

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

例如:

A->B->C->空

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

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

在上面删除 C 后的例子中,列表应该看起来像

A->B->空而不是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--;
  }
  }

修复了所有问题。

法典:

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--;
    }
}

这样的应该可以工作

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 emptyn");
 }
} 

最后最容易删除的代码是:

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