Create and Initialize Doubly Linked List in DSA C - Time & Space Complexity
When we create and initialize a doubly linked list, we want to know how the time needed grows as we add more nodes.
We ask: How long does it take to build the list as its size increases?
Analyze the time complexity of the following code snippet.
struct Node {
int data;
struct Node* prev;
struct Node* next;
};
struct Node* createList(int n) {
struct Node* head = NULL;
struct Node* temp = NULL;
for (int i = 0; i < n; i++) {
struct Node* newNode = malloc(sizeof(struct Node));
newNode->data = i;
newNode->prev = temp;
newNode->next = NULL;
if (temp != NULL) temp->next = newNode;
else head = newNode;
temp = newNode;
}
return head;
}
This code creates a doubly linked list with n nodes, linking each new node to the previous one.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop that runs n times to create and link nodes.
- How many times: Exactly once for each node from 0 to n-1, so n times.
Each new node requires a fixed number of steps to create and link it. So, as n grows, the total steps grow in a straight line.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 node creations and linkings |
| 100 | About 100 node creations and linkings |
| 1000 | About 1000 node creations and linkings |
Pattern observation: The work grows directly with n; doubling n doubles the work.
Time Complexity: O(n)
This means the time to create the list grows linearly with the number of nodes.
[X] Wrong: "Creating each node takes constant time, so the whole list creation is constant time."
[OK] Correct: Even though each node is made quickly, you must do it n times, so total time grows with n, not stays the same.
Understanding how list creation scales helps you explain efficiency clearly and shows you know how data structures behave as they grow.
"What if we added nodes at the head instead of the tail? How would the time complexity change?"
Practice
doubly linked list in data structures?Solution
Step 1: Understand doubly linked list structure
A doubly linked list has nodes with pointers to both next and previous nodes.Step 2: Identify traversal capability
This structure allows moving forward and backward through the list easily.Final Answer:
To allow traversal in both forward and backward directions -> Option AQuick Check:
Doubly linked list = bidirectional traversal [OK]
- Confusing doubly linked list with singly linked list
- Thinking it sorts data automatically
- Assuming it uses arrays internally
Solution
Step 1: Check node structure for doubly linked list
Each node must have data, a pointer to next node, and a pointer to previous node.Step 2: Identify correct syntax
struct Node { int data; struct Node* prev; struct Node* next; }; correctly declares pointers to next and prev nodes usingstruct Node*.Final Answer:
struct Node { int data; struct Node* prev; struct Node* next; }; -> Option BQuick Check:
Node has data + prev pointer + next pointer [OK]
- Using int instead of pointer for next/prev
- Missing prev pointer in node
- Declaring next/prev as struct Node instead of pointer
typedef struct Node {
int data;
struct Node* prev;
struct Node* next;
} Node;
int main() {
Node* head = (Node*)malloc(sizeof(Node));
Node* second = (Node*)malloc(sizeof(Node));
head->data = 10;
head->prev = NULL;
head->next = second;
second->data = 20;
second->prev = head;
second->next = NULL;
printf("%d -> %d -> NULL", head->data, second->data);
return 0;
}Solution
Step 1: Analyze node creation and linking
Two nodes are created: head with data 10, second with data 20. head->next points to second, second->prev points to head.Step 2: Understand print statement
Prints head->data (10), then second->data (20), then "-> NULL".Final Answer:
10 -> 20 -> NULL -> Option CQuick Check:
Prints data in order: 10 then 20 [OK]
- Confusing order of nodes
- Forgetting to set next or prev pointers
- Assuming print shows backward traversal
struct Node {
int data;
struct Node* prev;
struct Node* next;
};
int main() {
struct Node* node = malloc(sizeof(struct Node));
node->data = 5;
node->prev = NULL;
node->next = NULL;
free(node);
printf("%d", node->data);
return 0;
}Solution
Step 1: Review memory allocation and freeing
Memory is allocated for node, initialized, then freed with free(node).Step 2: Identify invalid access
After freeing, code tries to print node->data, which accesses freed memory causing undefined behavior.Final Answer:
Accessing freed memory after free(node) -> Option AQuick Check:
Using pointer after free = error [OK]
- Ignoring use-after-free errors
- Forgetting to include stdlib.h (but not main error here)
- Assuming free deletes pointer variable
prev and next pointers?Solution
Step 1: Check initialization of first node
n1 has data=1, prev=NULL, next=NULL initially.Step 2: Link second node correctly
n2 has data=2, prev=n1, next=NULL; n1->next points to n2.Step 3: Link third node correctly
n3 has data=3, prev=n2, next=NULL; n2->next points to n3.Final Answer:
Code snippet B correctly sets prev and next pointers for all nodes -> Option DQuick Check:
Each node's prev and next link neighbors properly [OK]
- Not setting prev pointers for nodes after first
- Setting next pointers incorrectly
- Making circular links unintentionally
Ready to prove it?
Pass the test and this pattern moves unknown
