Bird
0
0
DSA Cprogramming

Delete Node at End in DSA C

Choose your learning style9 modes available
Mental Model
To remove the last item in a chain, find the second last and cut off its link to the last.
Analogy: Imagine a chain of paper clips linked together. To remove the last clip, you hold the second last clip and unhook the last one.
head -> 1 -> 2 -> 3 -> null
Dry Run Walkthrough
Input: list: 1 -> 2 -> 3 -> null, delete node at end
Goal: Remove the last node so the list ends at node 2
Step 1: start at head node 1
head -> [1] -> 2 -> 3 -> null
Why: We begin from the start to find the second last node
Step 2: move to node 2, check next node
head -> 1 -> [2] -> 3 -> null
Why: We need to find the node before the last one
Step 3: node 2's next is node 3 which is last, set node 2's next to null
head -> 1 -> 2 -> null
Why: Cutting off the last node removes it from the list
Result:
head -> 1 -> 2 -> null
Annotated Code
DSA C
#include <stdio.h>
#include <stdlib.h>

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

// Function to delete node at end
void deleteAtEnd(struct Node** head_ref) {
    if (*head_ref == NULL) return; // empty list

    if ((*head_ref)->next == NULL) { // only one node
        free(*head_ref);
        *head_ref = NULL;
        return;
    }

    struct Node* temp = *head_ref;
    // move to second last node
    while (temp->next->next != NULL) {
        temp = temp->next;
    }

    free(temp->next); // free last node
    temp->next = NULL; // cut link to last node
}

// Function to print list
void printList(struct Node* head) {
    struct Node* temp = head;
    while (temp != NULL) {
        printf("%d -> ", temp->data);
        temp = temp->next;
    }
    printf("null\n");
}

// Driver code
int main() {
    struct Node* head = malloc(sizeof(struct Node));
    head->data = 1;
    head->next = malloc(sizeof(struct Node));
    head->next->data = 2;
    head->next->next = malloc(sizeof(struct Node));
    head->next->next->data = 3;
    head->next->next->next = NULL;

    deleteAtEnd(&head);
    printList(head);

    // Free remaining nodes
    while (head != NULL) {
        struct Node* temp = head;
        head = head->next;
        free(temp);
    }
    return 0;
}
if (*head_ref == NULL) return; // empty list
handle empty list by returning immediately
if ((*head_ref)->next == NULL) { free(*head_ref); *head_ref = NULL; return; }
handle single node list by freeing and setting head to null
while (temp->next->next != NULL) { temp = temp->next; }
advance temp to second last node
free(temp->next); temp->next = NULL;
free last node and cut link from second last
OutputSuccess
1 -> 2 -> null
Complexity Analysis
Time: O(n) because we traverse the list once to find the second last node
Space: O(1) because we only use a few pointers regardless of list size
vs Alternative: Compared to removing from the front which is O(1), deleting at end requires traversal making it slower
Edge Cases
empty list
function returns immediately without error
DSA C
if (*head_ref == NULL) return; // empty list
single node list
node is freed and head set to null
DSA C
if ((*head_ref)->next == NULL) { free(*head_ref); *head_ref = NULL; return; }
When to Use This Pattern
When you need to remove the last item in a linked list, look for the pattern of finding the second last node and cutting its link.
Common Mistakes
Mistake: Trying to free the last node without updating the second last node's next pointer
Fix: Always set the second last node's next pointer to null after freeing the last node
Summary
Deletes the last node from a singly linked list.
Use when you want to remove the tail element from a linked list.
The key is to find the second last node and set its next pointer to null.