簡體   English   中英

從單鏈表中刪除節點

[英]deleting node from a singly linked list

我有一個簡單的 function 從單個鏈表中搜索具有給定鍵的節點並將其刪除。 function 在具有給定鍵的節點無處不在時工作,除非該節點是列表的頭部。 為什么會這樣?

#include<stdio.h>
#include<stdlib.h>


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

void printlist(struct Node* node){
    while(node!=NULL){
        printf("%d", node->data);
        node = node->next;
    }
    printf("\n");
}

/* Given a reference (pointer to pointer) to the head of a list 
   and a key, deletes the first occurrence of key in linked list */
void deleteNode(struct Node* head, int key){
    if(head->data==key){
        head = head->next;
    }
    else {
        while(head->next->data!=key){
            head = head->next;
        }
        head->next = head->next->next;
    }
}

int main(){

    struct Node* first = (struct Node*)malloc(sizeof(struct Node));
    struct Node* second = (struct Node*)malloc(sizeof(struct Node));
    struct Node* third = (struct Node*)malloc(sizeof(struct Node));
    first->data = 1;
    second->data = 2;
    third->data = 3;
    first->next = second;
    second->next = third;
    third->next = NULL;

    printlist(first); // prints 123

    deleteNode(first, 2);  
    printlist(first); // prints 13

    deleteNode(first, 1);
    printlist(first); // still prints 13
}

當您調用此 function: void deleteNode(struct Node* head, int key)時,第一個參數是指向Node結構的指針(就像您在main中所做的兩次一樣),那么 function 作為其第一個參數接收的是你給的指針的副本

您可能知道 function: void Increment(int n)可以對傳遞的n做任何事情,而無需更改調用模塊中的變量。 因此,如果您希望 function 實際更改調用塊中的值,請給它一個指針:

void Increment(int* n) {
    ++(*n);
}

同樣,如果您希望 function 更改指針,則必須將指針傳遞給該指針 嘗試這個:

void deleteNode(struct Node** head, int key){
    Node* temp = *head;
    if(temp->data==key){
        *head = temp->next; // Only need to change *head if its the first one ...
    }
    else {
        while(temp->next->data!=key){
            temp = temp->next;
        }
        temp->next = temp->next->next; // ... else we have already changed the actual "links"
    }
}

並且,在main中,使用:

deleteNode(&first, 2);

和:

deleteNode(&first, 1);

讓我們知道會發生什么。

注意:順便說一句,這不是“最好的代碼”——通過刪除鏈接而不實際刪除指向的 object,您正在創建 memory 泄漏。

注意 2:另外,如果沒有找到key ,當它找到 NULL next指針時,您的代碼將“脫落”到列表的末尾!

function 處理原始磁頭的副本。 因此副本的更改不會影響原始節點。 您應該通過指針通過引用傳遞頭節點,或者從 function 返回更改后的頭節點。 您還必須檢查 function 的開頭是否等於 NULL。 否則 function 可以調用未定義的行為。

例如

void deleteNode( struct Node **head, int key )
{
    while( *head != NULL && ( *head )->data != key ) head = &( *head )->next;

    if ( *head != NULL ) *head = ( *head )->next;
}

並稱它為

deleteNode( &first, 1 );

這是一個演示程序

#include<stdio.h>
#include<stdlib.h>

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

void printlist(struct Node* node){
    while(node!=NULL){
        printf("%d", node->data);
        node = node->next;
    }
    printf("\n");
}

/* Given a reference (pointer to pointer) to the head of a list 
   and a key, deletes the first occurrence of key in linked list */
void deleteNode( struct Node **head, int key )
{
    while( *head != NULL && ( *head )->data != key ) head = &( *head )->next;

    if ( *head != NULL ) *head = ( *head )->next;
}

int main(){

    struct Node* first = (struct Node*)malloc(sizeof(struct Node));
    struct Node* second = (struct Node*)malloc(sizeof(struct Node));
    struct Node* third = (struct Node*)malloc(sizeof(struct Node));
    first->data = 1;
    second->data = 2;
    third->data = 3;
    first->next = second;
    second->next = third;
    third->next = NULL;

    printlist(first); // prints 123

    deleteNode(&first, 2);  
    printlist(first); // prints 13

    deleteNode(&first, 1);
    printlist(first); // still prints 13
}

它的 output 是

123
13
3

或者

struct Node * deleteNode( struct Node *head, int key )
{
    if ( head != NULL )
    {
        if ( head->data == key )
        {
            head = head->next;
        }
        else 
        {
            struct Node *current = head;
            while( current->next != NULL && current->next->data != key )
            {
                current = current->next;
            }
            if ( current->next != NULL ) current->next = current->next->next;
        }
    }

    return head;
}

並稱它為

first = deleteNode( first, 1 );

這是另一個演示程序

#include<stdio.h>
#include<stdlib.h>

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

void printlist(struct Node* node){
    while(node!=NULL){
        printf("%d", node->data);
        node = node->next;
    }
    printf("\n");
}

/* Given a reference (pointer to pointer) to the head of a list 
   and a key, deletes the first occurrence of key in linked list */
    struct Node * deleteNode( struct Node *head, int key )
    {
        if ( head != NULL )
        {
            if ( head->data == key )
            {
                head = head->next;
            }
            else 
            {
                struct Node *current = head;
                while( current->next != NULL && current->next->data != key )
                {
                    current = current->next;
                }
                if ( current->next != NULL ) current->next = current->next->next;
            }
        }

        return head;
    }

int main(){

    struct Node* first = (struct Node*)malloc(sizeof(struct Node));
    struct Node* second = (struct Node*)malloc(sizeof(struct Node));
    struct Node* third = (struct Node*)malloc(sizeof(struct Node));
    first->data = 1;
    second->data = 2;
    third->data = 3;
    first->next = second;
    second->next = third;
    third->next = NULL;

    printlist(first); // prints 123

    first = deleteNode(first, 2);  
    printlist(first); // prints 13

    first = deleteNode(first, 1);
    printlist(first); // still prints 13
}

再次,它的 output 是

123
13
3

通常,列表的節點是動態分配的。 所以刪除節點的 function 也應該釋放被刪除的節點或從 function 中返回。

暫無
暫無

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

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