簡體   English   中英

從 C 中的雙鏈表中刪除一個元素

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

該程序用於從雙鏈表中刪除節點並打印出新列表

該代碼幾乎適用於所有測試用例,除非要刪除的元素是列表末尾的倒數第二個元素。 當給定的時候,我在刪除 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();
}

這似乎有一些世界限制,所以讓我試着很快填滿。 因為我真的很想贏得一些聲譽,最后問了一大堆我想問的東西。 [1]: https://i.stack.imgur.com/Nke8q.png

temp指向要刪除的節點並且它是倒數第二個節點時,則 temp- temp->next不是 null 而是 temp- temp->next->next ,並且您的代碼嘗試執行temp->next->next->prev = temp; . 由於 temp- temp->next->next是 null,使用 temp- temp->next->next->prev不起作用。 你需要重新思考你的代碼在做什么以及為什么。

該代碼幾乎適用於所有測試用例,除非要刪除的元素是列表末尾的倒數第二個元素。

我不同意,原因如下:

您的delete() function 中存在多個問題。

  • 主要(您已經知道這一點) :如果列表中有超過1元素,並且為了刪除,用戶輸入倒數第二個要刪除的節點,則發生分段錯誤。 因為這個在delete()

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

temp- temp->next->nextNULL並且您的代碼正在嘗試訪問NULL指針。

  • 主要:如果列表僅包含一個元素,並且如果您將該元素作為輸入刪除,它將 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:如果列表中有超過1元素,並且為了刪除,用戶輸入了除最后一個和倒數第二個節點之外的任何要刪除的節點, delete()將最終刪除用戶輸入的節點旁邊的節點(其中應該是刪除)。 此外,在這種情況下還存在 memory 泄漏。

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

所有語句都在temp->next指針中進行更改,而不是在temp指針中進行更改。 此外,已刪除的節點 memory 不會在任何地方釋放。

  • Major:如果列表中有超過1元素,並且為了刪除,用戶輸入了最后一個節點,則不會發生刪除,最后一個節點將保留在列表中。 因為這個在delele()

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

如果temp指向最后一個節點,則 temp- temp->next將是NULL

  • 次要:如果列表中有超過1元素,並且為了刪除,用戶輸入了列表中不存在的某個節點,而不是沒有 output 消息通知用戶。

display() function:

  • 主要:通過NULLdisplay() function 會出現分段錯誤。 當您的列表只有一個元素並且該元素將被刪除然后列表將為空並且在delete()之后調用display()時,就會出現這種情況,這將導致分段錯誤。 這是因為在display()中:

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

如果tempNULL那么它將嘗試訪問NULL指針,它是 UB。

要刪除雙向鏈表中的節點,您需要注意它的上一個和下一個指針。 前一個的下一個應重置為其下一個節點,下一個的前一個應重置為其前一個節點。 如果它的前一個是NULL ,這意味着它的列表的第一個節點,在這種情況下,將列表的head重置為指向它的下一個節點。

執行:

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

還需要修復顯示器。 它應該是這樣的:

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

要刪除cur指向的元素,需要重定向前一個的指針next和后一個的指針pred ,前提是這些元素存在。 獲取這些元素

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

現在分流

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

並釋放當前元素:

delete cur;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM