Bird
0
0
DSA Cprogramming

Insert at Specific Position in Doubly Linked List in DSA C

Choose your learning style9 modes available
Mental Model
A doubly linked list lets you move forward and backward through nodes. To insert at a specific spot, you find that spot and adjust the links around it.
Analogy: Imagine a train with cars connected front and back. To add a new car in the middle, you disconnect the cars at that spot, insert the new car, then reconnect the cars before and after it.
head -> 1 ↔ 2 ↔ 3 ↔ 4 ↔ null
          ↑
Dry Run Walkthrough
Input: list: 1 ↔ 2 ↔ 4 ↔ null, insert value 3 at position 3
Goal: Insert the value 3 at the 3rd position so the list becomes 1 ↔ 2 ↔ 3 ↔ 4 ↔ null
Step 1: start at head node (1)
head -> [1] ↔ 2 ↔ 4 ↔ null
Why: We begin from the start to find the insertion point
Step 2: move to next node (2)
head -> 1 ↔ [2] ↔ 4 ↔ null
Why: We move forward to reach position 2, just before insertion point
Step 3: create new node with value 3
new_node(3) created, not linked yet
Why: Prepare the new node to insert
Step 4: link new node between 2 and 4
head -> 1 ↔ 2 ↔ [3] ↔ 4 ↔ null
Why: Adjust pointers to insert new node at position 3
Result:
head -> 1 ↔ 2 ↔ 3 ↔ 4 ↔ null
Annotated Code
DSA C
#include <stdio.h>
#include <stdlib.h>

// Node structure for doubly linked list
typedef struct Node {
    int data;
    struct Node* prev;
    struct Node* next;
} Node;

// Create a new node with given data
Node* createNode(int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->prev = NULL;
    newNode->next = NULL;
    return newNode;
}

// Insert node at specific position (1-based index)
void insertAtPosition(Node** head, int data, int position) {
    Node* newNode = createNode(data); // create new node
    if (position == 1) { // insert at head
        newNode->next = *head; // new node points to current head
        if (*head != NULL) {
            (*head)->prev = newNode; // current head points back to new node
        }
        *head = newNode; // update head to new node
        return;
    }

    Node* curr = *head;
    int count = 1;
    // move to node before insertion point
    while (curr != NULL && count < position - 1) {
        curr = curr->next; // advance curr
        count++;
    }

    if (curr == NULL) { // position is beyond list length
        free(newNode); // free unused node
        return; // do nothing
    }

    newNode->next = curr->next; // new node points to next node
    newNode->prev = curr; // new node points back to curr
    if (curr->next != NULL) {
        curr->next->prev = newNode; // next node points back to new node
    }
    curr->next = newNode; // curr points forward to new node
}

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

int main() {
    // Create initial list: 124
    Node* head = createNode(1);
    Node* second = createNode(2);
    Node* fourth = createNode(4);
    head->next = second;
    second->prev = head;
    second->next = fourth;
    fourth->prev = second;

    // Insert 3 at position 3
    insertAtPosition(&head, 3, 3);

    // Print final list
    printList(head);
    return 0;
}
Node* newNode = createNode(data);
create new node with given data
if (position == 1) { ... }
handle insertion at head separately
while (curr != NULL && count < position - 1) { curr = curr->next; count++; }
move curr to node before insertion point
if (curr == NULL) { free(newNode); return; }
guard against invalid position beyond list length
newNode->next = curr->next; newNode->prev = curr;
link new node forward and backward
if (curr->next != NULL) { curr->next->prev = newNode; }
adjust next node's prev pointer if exists
curr->next = newNode;
link current node forward to new node
OutputSuccess
1 ↔ 2 ↔ 3 ↔ 4 ↔ null
Complexity Analysis
Time: O(n) because we may need to traverse up to n nodes to reach the insertion point
Space: O(1) because we only create one new node and use a few pointers
vs Alternative: Compared to inserting in an array which requires shifting elements (O(n)), doubly linked list insertion only needs pointer changes (O(1) after traversal)
Edge Cases
insert at position 1 (head insertion)
new node becomes new head, previous head's prev pointer updated
DSA C
if (position == 1) { ... }
insert at position beyond list length
insertion is ignored, new node freed to avoid memory leak
DSA C
if (curr == NULL) { free(newNode); return; }
insert into empty list at position 1
new node becomes head with next and prev as NULL
DSA C
if (position == 1) { ... }
When to Use This Pattern
When you need to add an element at a specific place in a list that allows backward and forward moves, use doubly linked list insertion to adjust pointers efficiently.
Common Mistakes
Mistake: Not updating the prev pointer of the node after the inserted node
Fix: Always set curr->next->prev = newNode if curr->next is not NULL
Mistake: Not handling insertion at head separately
Fix: Check if position is 1 and update head pointer and prev links accordingly
Summary
Inserts a new node at a given position in a doubly linked list by adjusting next and prev pointers.
Use when you want to add an element anywhere in a list that supports forward and backward traversal.
The key is to carefully update four pointers around the insertion point to keep the list connected.