Delete Node - Linked List - C

泪湿孤枕 提交于 2021-01-29 02:20:24

问题


I am trying to delete a node from a linked list but I am still new to the concept of double pointers so I tried using a global variable to hold the head pointer instead. However, I get the wrong results when I try to print my list after deleting the middle node.

I saw this question deleting a node in the middle of a linked list and I don't know how is my delete node function different from the answer.

Here is my code:

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

typedef unsigned char u8;
typedef struct Node node;
void addfirstnode( u8 );
void addnode( u8 );
void print( void );
void deletenode( u8 key );
void deleteonlynode();
void deletefirstnode();

struct Node
{
    u8 x;
    node *next;
};
node *head;
u8 length = 0;


void main( void )
{
    u8 x;
    printf( "\nTo add node enter 0\nTo print linked list enter 1\nTo exit press 2\nTo delete node press 3\nYour Choice:" );
    scanf( "%d", &x );
    if ( x == 2 )
    {
        printf( "\nThank You\nGood Bye" );
    }
    while ( x != 2 )
    {
        switch ( x )
        {
            u8 n;
            u8 key;
            case 0:            //Add node
                printf( "\nPlease enter first value:" );
                scanf( "%d", &n );
                if ( length == 0 )
                {
                    addfirstnode( n );
                    //printf("%d",head->x);
                }
                else
                {
                    addnode( n );
                }
                printf( "\nNode added , Thank you\n" );
                break;

            case 1:            //Print
                print();
                break;

            case 3:            //DeleteNode
                printf( "\nPlease enter value to be deleted:" );
                scanf( "%d", &key );
                deletenode( key );
                //deletefirstnode();
                break;

            default:
                printf( "\nInvalid Choice please try again\n" );
        }
        printf( "\nTo add node enter 0\nTo print linked list enter 1\nTo exit press 2\nTo delete node press 3\nYour Choice:" );
        scanf( "%d", &x );
        if ( x == 2 )
        {
            printf( "\nThank You\nGood Bye" );
        }
    }
    //where do I use free();
}

void addfirstnode( u8 n )
{
    head = ( node * ) malloc( sizeof( node ) );
    head->next = NULL;
    head->x = n;
    length++;
}

void addnode( u8 n )
{
    node *last = head;
    while ( ( last->next ) != NULL )
    {
        last = last->next;
    }
    last->next = ( node * ) malloc( sizeof( node ) );
    ( last->next )->next = NULL;
    ( last->next )->x = n;
    length++;
}

void print( void )
{
    node *last = head;
    u8 count = 1;
    printf( "\n---------------------" );
    if ( last == NULL )
    {
        printf( "\nList is empty" );
    }
    while ( last != NULL )
    {
        printf( "\nNode Number %d = %d", count, last->x );
        last = last->next;
        count++;
    }
    printf( "\n---------------------" );
    printf( "\n" );
}

void deletenode( u8 key )
{
    node *last = head;
    //node*postlast = NULL;
    if ( ( last->x == key ) && ( last->next == NULL ) )
    {
        deleteonlynode();
    }
    else
    {
        while ( last != NULL )
        {
            if ( ( last->x ) == key )
            {
                printf( "value to be deleted is found" );
                node *temp = last->next;
                last->next = last->next->next;
                free( temp );
                length--;
            }
            last = last->next;
        }
    }
}

void deleteonlynode()
{
    printf( "\n Deleting the only node" );
    free( head );
    head = NULL;
    length--;
}

void deletefirstnode()
{
    printf( "\n Deleting the first node" );
    node *temp = head;
    head = head->next;
    free( temp );
    length--;
}

回答1:


The code is removing the wrong item from the linked list:

See:

        if ( ( last->x ) == key )
        {
            printf( "value to be deleted is found" );
            node *temp = last->next;     // last->next? No, just last.
            last->next = last->next->next;
            free( temp );
            length--;
        }

last is pointing at the element to be removed. But then the code assigns temp to point at last->next (NOT last), and then cuts that from the list.

So by looking at node->next rather than the current node, it's possible to trim it out since you're starting from the pointer before the one to remove. Basically your code was almost there already.

void deletenode( u8 key )
{
    node *ptr = head;

    if ( ( ptr->x == key ) )
    {
        // Delete the first/head element
        node *temp = ptr;
        head = head->next;
        free( temp );
        length--;
    }
    else
    {
        while ( ptr->next != NULL )
        {
            if ( ( ptr->next->x ) == key )
            {
                printf( "value to be deleted is found" );
                node *temp = ptr->next;
                ptr->next = ptr->next->next;
                free( temp );
                length--;
            }
            ptr = ptr->next;
        }
    }
}

Also I took the liberty of renaming last to ptr because it was confusing me.

EDIT: Updated to remove the head cleanly too.




回答2:


Your code seems to be deleting last->next while last should be the node that matches the key. I guess the following code may be shorter and do the deletion

node* head;

/* returns the node* the previous_node->next should be after the deletion */
node* delete_node(node* current, u8 key) {
    if (current == NULL) return NULL;  // deletion comes to end
    if (head->x == key) {
        node* temp = current->next;
        free(current);
        return delete_node(temp, key);
    }
    current->next = delete_node(current->next, key);
    return current;
}


int main() {
    // build the linked list
    // ...
    head = delete_node(head, key);
    return 0;
}

However, this implement (which uses recursion instead of loop) may cause StackOverFlow if the list is too long. I had not tested if gcc would optimize the recursion out.



来源:https://stackoverflow.com/questions/53698653/delete-node-linked-list-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!