jypi
  • Explore
ChatWays to LearnMind mapAbout

jypi

  • About Us
  • Our Mission
  • Team
  • Careers

Resources

  • Ways to Learn
  • Mind map
  • Blog
  • Help Center
  • Community Guidelines
  • Contributor Guide

Legal

  • Terms of Service
  • Privacy Policy
  • Cookie Policy
  • Content Policy

Connect

  • Twitter
  • Discord
  • Instagram
  • Contact Us
jypi

© 2026 jypi. All rights reserved.

CS50 - Introduction to Computer Science
Chapters

1Computational Thinking and Foundations

2C Language Basics

3Arrays, Strings, and Algorithmic Basics

4Algorithm Efficiency and Recursion

5Memory, Pointers, and File I/O

6Core Data Structures in C

Linked Lists: Nodes and PointersList Insertion and DeletionDoubly Linked ListsStacks and LIFOQueues and FIFOHash Tables OverviewHash Functions and CollisionsChaining vs Open AddressingLoad Factor and ResizingTries and Prefix MatchingTrees and Binary Search TreesTree TraversalsSets and Maps via HashingGraphs and Adjacency ListsChoosing a Data Structure

7Python Fundamentals

8Object-Oriented and Advanced Python

9Relational Databases and SQL

10Web Foundations: HTML, CSS, and JavaScript

11Servers and Flask Web Applications

12Cybersecurity and Privacy Essentials

13Software Engineering Practices

14Version Control and Collaboration

15Capstone: Designing, Building, and Presenting

Courses/CS50 - Introduction to Computer Science/Core Data Structures in C

Core Data Structures in C

11430 views

Implement and compare foundational data structures for performance and use cases.

Content

2 of 15

List Insertion and Deletion

List Insertion and Deletion in C | CS50 Core Data Structures
4583 views
beginner
computer-science
C
linked-lists
humorous
gpt-5-mini
4583 views

Versions:

List Insertion and Deletion in C | CS50 Core Data Structures

Watch & Learn

AI-discovered learning video

Sign in to watch the learning video for this topic.

Sign inSign up free

Start learning for free

Sign up to save progress, unlock study materials, and track your learning.

  • Bookmark content and pick up later
  • AI-generated study materials
  • Flashcards, timelines, and more
  • Progress tracking and certificates

Free to join · No credit card required

List Insertion and Deletion in C — The Moveable Feast of Linked Lists

"If pointers are the secret handshake of C, inserting and deleting nodes is the part where you learn the dance steps — and occasionally step on memory's toes."

You're coming in hot from "Nodes and Pointers" (so I won't re-explain what a node is), and you've already wrestled with malloc, free, and pointer arithmetic in "Memory, Pointers, and File I/O." Perfect — now we combine those muscles and learn how to add and remove list elements safely, efficiently, and without leaking your dignity (or memory).


Why this matters (and where you'll see it)

  • Linked lists are the classic dynamic data structure: flexible size, cheap insertions/deletions when you know the spot.
  • Real-world uses: building stacks/queues, adjacency lists in graphs, undo histories, or any place where array resizing would be a pain.
  • Practically: learning correct insertion/deletion teaches pointer manipulation, lifetime management (malloc/free), and defensive programming — all CS50 essentials.

Core operations we'll cover

  1. Insert at head
  2. Insert at tail
  3. Insert after a given node (or by value)
  4. Delete head
  5. Delete a given node (by pointer or by value)
  6. Delete the entire list (free everything)

We'll show canonical C implementations, then explain pitfalls, complexity, and debugging tips.


The basic node type (reminder)

typedef struct node {
    int value;
    struct node *next;
} node;

This is the same node you met earlier. Remember: nodes live on the heap (malloc) unless you intentionally make them local. That matters when you free.


1) Insert at head — the simplest magical trick

Why: O(1) time. No traversal. Great for stacks.

node *insert_head(node *head, int val) {
    node *n = malloc(sizeof(node));
    if (!n) return head; // malloc failed — leave list unchanged
    n->value = val;
    n->next = head;
    return n; // new head
}

Micro explanation: You create a new node, point it to the old head, and return the new node as head. No loops, no previous-pointer juggling.


2) Insert at tail — two common approaches

A) Simple: traverse to end (O(n)).

node *insert_tail(node *head, int val) {
    node *n = malloc(sizeof(node));
    if (!n) return head;
    n->value = val;
    n->next = NULL;
    if (!head) return n; // empty list -> new head

    node *cur = head;
    while (cur->next) cur = cur->next;
    cur->next = n;
    return head;
}

B) Efficient for repeated tails: keep a tail pointer alongside head (amortized O(1) append).


3) Insert after a given node (or keep list sorted)

Insert after a specific node pointer:

void insert_after(node *prev, int val) {
    if (!prev) return; // nothing to insert after
    node *n = malloc(sizeof(node));
    if (!n) return;
    n->value = val;
    n->next = prev->next;
    prev->next = n;
}

Insert in sorted order: traverse to find insertion spot and use the same link tweaks.


4) Delete head

node *delete_head(node *head) {
    if (!head) return NULL;
    node *next = head->next;
    free(head);
    return next; // new head
}

Micro explanation: Save the pointer to head->next, free the old head, then return the saved pointer as new head. Never access freed memory.


5) Delete a node by value (the classic gotcha)

We must keep track of previous node to re-link. Edge case: deleting head.

node *delete_value(node *head, int val) {
    if (!head) return NULL;
    // Special case: head contains value
    if (head->value == val) return delete_head(head);

    node *prev = head;
    node *cur = head->next;
    while (cur) {
        if (cur->value == val) {
            prev->next = cur->next;
            free(cur);
            return head; // head unchanged
        }
        prev = cur;
        cur = cur->next;
    }
    return head; // not found
}

Pro tip: using a pointer-to-pointer (node **) can simplify head handling and reduce duplication.

Pointer-to-pointer deletion example:

void delete_value_pp(node **headp, int val) {
    node **curp = headp;
    while (*curp) {
        node *cur = *curp;
        if (cur->value == val) {
            *curp = cur->next; // unlink
            free(cur);
            return;
        }
        curp = &cur->next;
    }
}

Why this rule is beautiful: it treats head exactly like any other next pointer. No special-case code.


6) Free the whole list

void free_list(node *head) {
    node *cur = head;
    while (cur) {
        node *next = cur->next;
        free(cur);
        cur = next;
    }
}

Always free every malloc'd node before your program exits (or before losing the last pointer to them).


Complexity & common bugs

  • Time:
    • Insert at head: O(1)
    • Insert at tail (no tail pointer): O(n)
    • Search + insert/delete at arbitrary position: O(n)
  • Space: each node uses sizeof(node)

Common bugs:

  • Forgetting to set new_node->next (leads to garbage pointer)
  • Using freed memory (dangling pointer)
  • Double-freeing (freeing same node twice)
  • Memory leaks (not freeing nodes)
  • Not checking malloc result (NULL) on constrained systems

Debugging tools: valgrind (or LeakSanitizer), printing pointer values, and stepping through with a debugger.


Quick checklist before running your insertion/deletion code

  • Do you handle empty list (head == NULL)?
  • Do you update head when needed? (return new head or use node **)
  • Do you set next pointers correctly before freeing?
  • Do you free every node you allocate?
  • Did you check malloc for NULL in realistic environments?

Key takeaways — the memorable ones

  • Insertion/deletion = pointer surgery. If you tie the wrong knot, the list unravels.
  • Use insert at head for O(1) simplicity.
  • Use pointer-to-pointer to avoid annoying head special cases.
  • Always call free for nodes you created with malloc — valgrind will judge you otherwise.

"If you can picture the pointers in your head, you're 80% there. The rest is careful coding and, occasionally, pleading with your debugger."


If you want, I can:

  • Show an integrated example program (main) that builds a list, inserts/deletes, and prints results.
  • Convert examples to work with strings (remember strdup and free!).
  • Walk through a valgrind output and show what an actual leak looks like.

Tags: beginner, C, linked-lists, humorous, computer-science

Flashcards
Mind Map
Speed Challenge

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!

Ready to practice?

Sign up now to study with flashcards, practice questions, and more — and track your progress on this topic.

Study with flashcards, timelines, and more
Earn certificates for completed courses
Bookmark content for later reference
Track your progress across all topics