简体   繁体   English

从 C 中的双链表中删除一个元素

[英]Deleting an element from double linked list in C

The program is for deleting a node from a double linked list and printing out the new list该程序用于从双链表中删除节点并打印出新列表

The code works great for almost every testcase except when the element to be deleted is the 2nd last element from the end of the list.该代码几乎适用于所有测试用例,除非要删除的元素是列表末尾的倒数第二个元素。 When that is given I get a segmentation fault error in my delete function, which i just have not been able to fix and hope to get fixed.当给定的时候,我在删除 function 时遇到分段错误错误,我只是无法修复并希望得到修复。

#include <stdio.h>
#include <stdlib.h>
//no work
struct node{
    int data;
    struct node *next;
    struct node *prev;
};

struct node *head = NULL;
void display();
void addnode(int x){
    struct node *current = (struct node *)malloc(sizeof(struct node));

    current->data = x;
    current->next = NULL;
    current->prev = NULL;

    if (head == NULL)
        head = current;
    else{
        struct node *temp;
        for (temp = head; temp->next != NULL; temp = temp->next);
        temp->next = current;
        current->prev = temp;
    }
}

void delete(int t){
    struct node *temp;
    if (head->next == NULL){
        if (head->data != t)
            printf("Target Element is Not Found\n");
        else{
            display();
            printf("List is Empty\n");
        }
    }else{
        for (temp = head; temp->next != NULL && temp->data != t; temp = temp->next);
        if (temp->data == t){
            if (temp->next != NULL){
                temp->next->next->prev = temp;
                temp->next = temp->next->next;
            }
        }
    }
}

void display(){
    struct node *temp;
    printf("List->");
    for (temp = head; temp->next != NULL; temp = temp->next)
        printf("%d ", temp->data);
    printf("%d->NULL\n", temp->data);
}

int main(){
    int n, temp;
    scanf("%d", &n);

    while (n--){
        scanf("%d", &temp);
        addnode(temp);
    }
    int t;
    scanf("%d", &t);
    
    display();
    delete(t);
    display();
}

There seem to be some world limit for this so let me try to fill that up very quick.这似乎有一些世界限制,所以让我试着很快填满。 Cuz i really want to earn some reputation and finally ask a whole bunch of stuff i wanted to ask.因为我真的很想赢得一些声誉,最后问了一大堆我想问的东西。 [1]: https://i.stack.imgur.com/Nke8q.png [1]: https://i.stack.imgur.com/Nke8q.png

When temp points to the node to be deleted, and it is the next-to-last, then temp->next is not null but temp->next->next is, and your code attempts to execute temp->next->next->prev = temp;temp指向要删除的节点并且它是倒数第二个节点时,则 temp- temp->next不是 null 而是 temp- temp->next->next ,并且您的代码尝试执行temp->next->next->prev = temp; . . Since temp->next->next is null, using temp->next->next->prev does not work.由于 temp- temp->next->next是 null,使用 temp- temp->next->next->prev不起作用。 You need to rethink what your code is doing and why.你需要重新思考你的代码在做什么以及为什么。

The code works great for almost every testcase except when the element to be deleted is the 2nd last element from the end of the list.该代码几乎适用于所有测试用例,除非要删除的元素是列表末尾的倒数第二个元素。

I don't agree and below is the reason:我不同意,原因如下:

Multiple problems in your delete() function.您的delete() function 中存在多个问题。

  • Major (you are already aware of this) : If the list has more than 1 elements in it and, for deletion, user entered second last node to delete then segmentation fault is occurring.主要(您已经知道这一点) :如果列表中有超过1元素,并且为了删除,用户输入倒数第二个要删除的节点,则发生分段错误。 Its because of this in delete() :因为这个在delete()

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

temp->next->next is NULL and your code is attempting to access NULL pointer. temp- temp->next->nextNULL并且您的代码正在尝试访问NULL指针。

  • Major: If the list contain only one element and if you give that element as input to delete, it will output - List is Empty and node with that value will not be deleted:主要:如果列表仅包含一个元素,并且如果您将该元素作为输入删除,它将 output - List is Empty并且具有该值的节点将不会被删除:

     if (head->next == NULL){ if (head->data;= t) printf("Target Element is Not Found\n"); else{ display(); printf("List is Empty\n"). }.... ....
  • Major: If the list has more than 1 elements in it and, for deletion, user entered any node to delete other than last and second last node, the delete() will end up deleting the node next to the node entered by user (which is supposed to be delete). Major:如果列表中有超过1元素,并且为了删除,用户输入了除最后一个和倒数第二个节点之外的任何要删除的节点, delete()将最终删除用户输入的节点旁边的节点(其中应该是删除)。 Moreover, there is memory leak in this scenario.此外,在这种情况下还存在 memory 泄漏。

     if (temp->data == t){ if (temp->next;= NULL){ temp->next->next->prev = temp; temp->next = temp->next->next. }.... ....

All statements are making changes in temp->next pointer and not in temp pointer.所有语句都在temp->next指针中进行更改,而不是在temp指针中进行更改。 Also, deleted node memory is not freed up anywhere.此外,已删除的节点 memory 不会在任何地方释放。

  • Major: If the list has more than 1 elements in it and, for deletion, user entered last node, no deletion will happen and the last node will remain part of list. Major:如果列表中有超过1元素,并且为了删除,用户输入了最后一个节点,则不会发生删除,最后一个节点将保留在列表中。 Its because of this in delele() :因为这个在delele()

     if (temp->data == t){ if (temp->next != NULL){

If temp is pointing to last node then temp->next will be NULL .如果temp指向最后一个节点,则 temp- temp->next将是NULL

  • Minor: If the list has more than 1 elements in it and, for deletion, user entered some node which does not exists in the list than no output message to inform this to the user.次要:如果列表中有超过1元素,并且为了删除,用户输入了列表中不存在的某个节点,而不是没有 output 消息通知用户。

Problem in display() function: display() function:

  • Major: Pass NULL to display() function and it will give segmentation fault.主要:通过NULLdisplay() function 会出现分段错误。 This will be the case when your list will have only one element and that element will be deleted then the list will be empty and when display() will be called after delete() , it will result in segmentation fault.当您的列表只有一个元素并且该元素将被删除然后列表将为空并且在delete()之后调用display()时,就会出现这种情况,这将导致分段错误。 It's because of this in display() :这是因为在display()中:

     for (temp = head; temp->next;= NULL; temp = temp->next) ^^^^^^^^^^

If temp is NULL then it will attempt to access NULL pointer which is UB.如果tempNULL那么它将尝试访问NULL指针,它是 UB。

To delete a node in doubly linked list, you need to take care of it's previous and next pointer.要删除双向链表中的节点,您需要注意它的上一个和下一个指针。 The next of previous should be reset to its next node and previous of next should be reset to its previous node.前一个的下一个应重置为其下一个节点,下一个的前一个应重置为其前一个节点。 If its previous is NULL that means its first node of the list and, in this case, reset the head of list to pointing to its next node.如果它的前一个是NULL ,这意味着它的列表的第一个节点,在这种情况下,将列表的head重置为指向它的下一个节点。

Implementation:执行:

void delete (int t) {
    struct node *temp;
    for (temp = head; temp != NULL && temp->data != t; temp = temp->next);

    if (temp == NULL) {
        printf("Target Element is Not Found\n");
        return;
    }

    if (temp->prev != NULL) {
        temp->prev->next = temp->next;
        temp->prev = NULL;
    }
    else {
        head = temp->next;
    }

    if (temp->next != NULL) {
        temp->next->prev = temp->prev;
        temp->next = NULL;
    }

    free (temp);
}

Need to fix the display as well.还需要修复显示器。 It should be like this:它应该是这样的:

void display (void) {
    struct node *temp;
    printf("List->");
    for (temp = head; temp != NULL; temp = temp->next)
        printf("%d ", temp->data);
    printf ("\n");
}

To delete the element pointed to by cur , you need to redirect the pointer next of the previous and the pointer pred of the following, provided these elements exist.要删除cur指向的元素,需要重定向前一个的指针next和后一个的指针pred ,前提是这些元素存在。 Get these elements with获取这些元素

node* pred= cur->pred, * next= cur->next;

Now shunt现在分流

(pred ? pred->next : head)= next;
(next ? next->pred : tail)= pred;

and release the current element:并释放当前元素:

delete cur;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM