Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

C Linked Lists

What is a Linked List?

A linked list is a dynamic data structure where each element (called a node) contains data and a pointer to the next node. Unlike arrays, linked lists do not require contiguous memory — nodes can be scattered anywhere in the heap.

FeatureArrayLinked List
MemoryContiguous, fixed sizeDynamic, scattered
Access by indexO(1) — directO(n) — traverse
Insert at beginningO(n) — shift elementsO(1)
Insert at endO(1) (if space)O(n) or O(1) with tail pointer
DeleteO(n) — shift elementsO(1) with pointer to node
Memory overheadNoneExtra pointer per node

Singly Linked List

Each node has data and a next pointer. The last node's next is NULL.

Singly Linked List — Full Implementation
#include <stdio.h>
#include <stdlib.h>

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

// Create a new node
Node* createNode(int data) {
    Node *node = (Node*)malloc(sizeof(Node));
    if (!node) { perror("malloc"); exit(1); }
    node->data = data;
    node->next = NULL;
    return node;
}

// Insert at beginning — O(1)
Node* insertFront(Node *head, int data) {
    Node *node = createNode(data);
    node->next = head;
    return node;  // new head
}

// Insert at end — O(n)
Node* insertEnd(Node *head, int data) {
    Node *node = createNode(data);
    if (!head) return node;
    Node *curr = head;
    while (curr->next) curr = curr->next;
    curr->next = node;
    return head;
}

// Delete a node by value — O(n)
Node* deleteNode(Node *head, int data) {
    if (!head) return NULL;
    if (head->data == data) {
        Node *temp = head->next;
        free(head);
        return temp;
    }
    Node *curr = head;
    while (curr->next && curr->next->data != data)
        curr = curr->next;
    if (curr->next) {
        Node *temp = curr->next;
        curr->next = temp->next;
        free(temp);
    }
    return head;
}

// Search — O(n)
int search(Node *head, int data) {
    int pos = 0;
    while (head) {
        if (head->data == data) return pos;
        head = head->next;
        pos++;
    }
    return -1;
}

// Print the list
void printList(Node *head) {
    while (head) {
        printf("%d", head->data);
        if (head->next) printf(" -> ");
        head = head->next;
    }
    printf(" -> NULL\n");
}

// Free all nodes
void freeList(Node *head) {
    while (head) {
        Node *temp = head;
        head = head->next;
        free(temp);
    }
}

int main() {
    Node *head = NULL;

    head = insertEnd(head, 10);
    head = insertEnd(head, 20);
    head = insertEnd(head, 30);
    head = insertFront(head, 5);

    printf("List: "); printList(head);
    // 5 -> 10 -> 20 -> 30 -> NULL

    head = deleteNode(head, 20);
    printf("After deleting 20: "); printList(head);
    // 5 -> 10 -> 30 -> NULL

    printf("Search 30: position %d\n", search(head, 30));  // 2
    printf("Search 99: position %d\n", search(head, 99));  // -1

    freeList(head);
    return 0;
}

Doubly Linked List

Each node has both a next and a prev pointer. This allows traversal in both directions and O(1) deletion when you have a pointer to the node.

Doubly Linked List
#include <stdio.h>
#include <stdlib.h>

typedef struct DNode {
    int data;
    struct DNode *prev;
    struct DNode *next;
} DNode;

DNode* createDNode(int data) {
    DNode *node = (DNode*)malloc(sizeof(DNode));
    node->data = data;
    node->prev = NULL;
    node->next = NULL;
    return node;
}

DNode* insertFront(DNode *head, int data) {
    DNode *node = createDNode(data);
    if (head) {
        node->next = head;
        head->prev = node;
    }
    return node;
}

void printForward(DNode *head) {
    printf("Forward:  ");
    DNode *tail = NULL;
    while (head) {
        printf("%d ", head->data);
        tail = head;
        head = head->next;
    }
    printf("\n");

    printf("Backward: ");
    while (tail) {
        printf("%d ", tail->data);
        tail = tail->prev;
    }
    printf("\n");
}

int main() {
    DNode *head = NULL;
    head = insertFront(head, 30);
    head = insertFront(head, 20);
    head = insertFront(head, 10);

    printForward(head);
    // Forward:  10 20 30
    // Backward: 30 20 10

    return 0;
}

Reverse a Linked List

Reverse a Singly Linked List
#include <stdio.h>
#include <stdlib.h>

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

Node* reverse(Node *head) {
    Node *prev = NULL;
    Node *curr = head;
    while (curr) {
        Node *next = curr->next;  // save next
        curr->next = prev;        // reverse link
        prev = curr;              // move prev forward
        curr = next;              // move curr forward
    }
    return prev;  // new head
}

// helper: build list from array
Node* buildList(int arr[], int n) {
    Node *head = NULL, *tail = NULL;
    for (int i = 0; i < n; i++) {
        Node *node = malloc(sizeof(Node));
        node->data = arr[i]; node->next = NULL;
        if (!head) head = tail = node;
        else { tail->next = node; tail = node; }
    }
    return head;
}

void printList(Node *h) {
    while (h) { printf("%d%s", h->data, h->next ? " -> " : "\n"); h = h->next; }
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    Node *head = buildList(arr, 5);
    printf("Original: "); printList(head);
    head = reverse(head);
    printf("Reversed: "); printList(head);
    return 0;
}
// Original: 1 -> 2 -> 3 -> 4 -> 5
// Reversed: 5 -> 4 -> 3 -> 2 -> 1

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.