Search code examples
clinked-listpass-by-reference

Delete first element in a linked sorted list


I'm new here and this is actually my first question.

I wrote this code and I can't delete the first element of the list, somehow I can delete other elements. I have also a problem with the function reverse_list and I believe it is because I did not pass the argument as a reference.

Can I use the & in the argument in C programming?

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

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


struct Node * build_sorted_list () {
    struct Node * head = NULL, * temp, * rear, * front;
    int num;
    printf ("please enter a number:");
    scanf ("%d", &num);
    while (num != 0) {
        temp = (struct Node *) malloc (sizeof (struct Node));
        if (temp == NULL) {
            printf ("god damn");
            break;
        }
        temp -> data = num;
        if (head == NULL) {
            temp -> next = NULL;
            head = temp;
        }
        else if (num <= head -> data) {
            temp -> next = head;
            head = temp;
        }
        else {
            rear = head;
            front = rear -> next;
            while (front != NULL && front -> data <= num) {
                rear = front;
                front = front -> next;
            }
            temp -> next = front;
            rear -> next = temp;
        }
        printf ("enter number please:\n");
        scanf ("%d", &num);
    }
    return head;
}


struct Node * reverse_list (struct Node * head) {
    struct Node * rear, * mid, * front;
    if (head != NULL || head -> next == NULL) {
        return head;
    }
    rear = head;
    mid = rear ->next;
    front = mid -> next;
    while (front != NULL) {
        mid -> next = rear;
        rear = mid;
        mid = front;
        front = front ->next;
    }
    mid -> next = rear;
    head -> next = NULL;
    head = mid;
    return head;
}


struct Node * delete_num (int wanted, struct Node * head) {
    struct Node * rear, * front;
    if (head == NULL) {
        return head;
    }
    if (head -> data == wanted) {
        struct Node * temp = head;
        head = head -> next;
        temp = NULL;
        return head;
    }
    rear = head;
    front = head -> next;
    while (front != NULL) {
        if (front -> data == wanted) {
            break;
        }
        rear = front;
        front = front -> next;
    }
    if (front != NULL) {
        rear -> next = front -> next;
    }
    free (front);
    return head;
}


int main() {
    struct Node * head;
    int wanted;
    head = build_sorted_list(); /* Please pretend this function exists */
    reverse_list (head);

    printf ("please enter a number to delete:");
    scanf ("%d", &wanted);
    delete_num (wanted, head);

    free_list (head);

    return 0;
}

Solution

  • As a rule of thumb with recursive functions that manage data structures. Operations on the structure should return the structure.

    By definition, a linked list is either:

    • An empty list.
    • A node with a value, and a linked list as its tail.

    A linked list has a recursive nature. You need to be very careful, recursive functions are very complex, despite the short amount of code.

    In your main function you have a head pointer. It's not safe to assume that the head will remain the same. In fact, your problem comes when you remove the first element (head).

    Your delete should be something like this:

    struct Node * delete_num(int wanted, struct Node * head){
        if( head == NULL)
            return NULL;    //Reached the end of the line, nothing to do.
    
        if( head->data != wanted )
            head->next = delete_num(wanted, head->next);    //Haven't reached it yet, but 
                                                            //the element must be down 
                                                            //the line, I want to update
                                                            //my next in case it's the 
                                                            //next node.
    
        if(head->data == wanted){
             struct Node * aux = head;
             head = head->next;
             free(aux);
        }
    
        return head;
    }
    

    This is assuming you only want to remove one element and your list doesn't admit repeated values.

    Your call to this function from main should be:

    head = delete_num(wanted, head);
    

    Andres