➕ Insertion Operations in Doubly Linked List (Beginning, End & Specific Position)
Welcome to Part 2 of our Doubly Linked List in Java series.
In Part 1A, we learned:
- ✅ What is a Doubly Linked List?
- ✅ Why do we need it?
- ✅ Structure of a Node
- ✅ Head and Tail
- ✅ Memory Representation
- ✅ Creating Nodes
In Part 1B, we learned:
- ✅ Creating a Doubly Linked List
- ✅ Connecting Nodes
- ✅ Forward Traversal
- ✅ Backward Traversal
Now it’s time to learn the most important operation of a Doubly Linked List—Insertion.
Unlike a Singly Linked List, a Doubly Linked List stores both previous and next references. Therefore, whenever a new node is inserted, both references must be updated correctly.
In this tutorial, you’ll learn:
- ➕ Insertion at the Beginning
- ➕ Insertion at the End
- ➕ Insertion at a Specific Position
- 💻 Complete Java Programs
- 🔍 Dry Runs
- 📈 Time Complexity
- 🎯 Interview Questions
Let’s begin!
📚 Table of Contents
- What is Insertion?
- Types of Insertion
- Insertion at Beginning
- Insertion at End
- Insertion at Specific Position
- Java Programs
- Dry Runs
- Time Complexity
- Common Mistakes
- FAQs
- Conclusion
➕ What is Insertion?
Insertion means adding a new node into a Doubly Linked List.
Example
Before insertion
NULL ← 10 ⇄ 20 ⇄ 30 → NULL
Insert
40
After insertion
NULL ← 10 ⇄ 20 ⇄ 30 ⇄ 40 → NULL
The new node becomes part of the linked list.
📌 Types of Insertion
There are three common insertion operations.
1️⃣ Insert at Beginning
Before
10 ⇄ 20 ⇄ 30
After inserting 5
5 ⇄ 10 ⇄ 20 ⇄ 30
2️⃣ Insert at End
10 ⇄ 20 ⇄ 30
After
10 ⇄ 20 ⇄ 30 ⇄ 40
3️⃣ Insert at Specific Position
10 ⇄ 20 ⇄ 40
Insert 30
10 ⇄ 20 ⇄ 30 ⇄ 40
🚀 Insertion at the Beginning
Suppose we have
Head
↓
NULL ← 10 ⇄ 20 ⇄ 30 → NULL
Insert
5
Step 1
Create a new node.
5
Step 2
Point the new node to the current head.
5 ⇄ 10
This requires two updates.
newNode.next = head
head.prev = newNode
Step 3
Move Head.
Head
↓
NULL ← 5 ⇄ 10 ⇄ 20 ⇄ 30
Done!
🎨 Visual Explanation
Before
NULL ← 10 ⇄ 20 ⇄ 30 → NULL
After
NULL ← 5 ⇄ 10 ⇄ 20 ⇄ 30 → NULL
Notice
Only three references change.
💻 Java Program – Insert at Beginning
class Node {
int data;
Node prev;
Node next;
Node(int data) {
this.data = data;
prev = null;
next = null;
}
}
public class DoublyLinkedList {
Node head;
public void insertAtBeginning(int data) {
Node newNode = new Node(data);
if(head == null){
head = newNode;
return;
}
newNode.next = head;
head.prev = newNode;
head = newNode;
}
public void display(){
Node temp = head;
while(temp != null){
System.out.print(temp.data + " ⇄ ");
temp = temp.next;
}
System.out.println("NULL");
}
public static void main(String args[]){
DoublyLinkedList list = new DoublyLinkedList();
list.insertAtBeginning(30);
list.insertAtBeginning(20);
list.insertAtBeginning(10);
list.display();
}
}
Output
10 ⇄ 20 ⇄ 30 ⇄ NULL
📈 Time Complexity
O(1)
🚀 Insertion at the End
Suppose
10 ⇄ 20 ⇄ 30
Insert
40
Result
10 ⇄ 20 ⇄ 30 ⇄ 40
Algorithm
- Create new node.
- Traverse to last node.
- Last node points to new node.
- New node points back to last node.
🎨 Visual Explanation
Current
10 ⇄ 20 ⇄ 30
New Node
40
Update
30.next = 40
40.prev = 30
Done.
💻 Java Program – Insert at End
public void insertAtEnd(int data){
Node newNode = new Node(data);
if(head == null){
head = newNode;
return;
}
Node temp = head;
while(temp.next != null){
temp = temp.next;
}
temp.next = newNode;
newNode.prev = temp;
}
Output
10 ⇄ 20 ⇄ 30 ⇄ 40 ⇄ NULL
🔍 Dry Run
Current
10 ⇄ 20 ⇄ 30
Traverse
10
↓
20
↓
30
Update
30.next = 40
40.prev = 30
Result
10 ⇄ 20 ⇄ 30 ⇄ 40
📈 Time Complexity
Traversal required.
O(n)
🚀 Insertion at a Specific Position
Suppose
10 ⇄ 20 ⇄ 40 ⇄ 50
Insert
30
at Position 3.
Result
10 ⇄ 20 ⇄ 30 ⇄ 40 ⇄ 50
📝 Algorithm
- Traverse to the node before the required position.
- Store the next node.
- Connect the new node with both neighbors.
- Update all references.
🎨 Visual Explanation
Current
20 ⇄ 40
Insert
30
Step 1
30.next = 40
Step 2
30.prev = 20
Step 3
20.next = 30
Step 4
40.prev = 30
Result
20 ⇄ 30 ⇄ 40
Notice
We updated four references.
💻 Java Program – Insert at Position
public void insertAtPosition(int position, int data){
Node newNode = new Node(data);
if(position == 1){
insertAtBeginning(data);
return;
}
Node temp = head;
for(int i=1;i<position-1 && temp!=null;i++){
temp = temp.next;
}
if(temp == null){
System.out.println("Invalid Position");
return;
}
if(temp.next == null){
temp.next = newNode;
newNode.prev = temp;
return;
}
newNode.next = temp.next;
newNode.prev = temp;
temp.next.prev = newNode;
temp.next = newNode;
}
Output
10 ⇄ 20 ⇄ 30 ⇄ 40 ⇄ 50
🔍 Dry Run
Current
10 ⇄ 20 ⇄ 40 ⇄ 50
Move to
20
Update
30.next = 40
Update
30.prev = 20
Update
20.next = 30
Update
40.prev = 30
Final
10 ⇄ 20 ⇄ 30 ⇄ 40 ⇄ 50
💻 Complete Java Program
class Node {
int data;
Node prev;
Node next;
Node(int data){
this.data = data;
prev = null;
next = null;
}
}
public class DoublyLinkedList {
Node head;
public void insertAtBeginning(int data){
Node newNode = new Node(data);
if(head == null){
head = newNode;
return;
}
newNode.next = head;
head.prev = newNode;
head = newNode;
}
public void insertAtEnd(int data){
Node newNode = new Node(data);
if(head == null){
head = newNode;
return;
}
Node temp = head;
while(temp.next != null)
temp = temp.next;
temp.next = newNode;
newNode.prev = temp;
}
public void insertAtPosition(int position,int data){
if(position == 1){
insertAtBeginning(data);
return;
}
Node newNode = new Node(data);
Node temp = head;
for(int i=1;i<position-1 && temp!=null;i++)
temp = temp.next;
if(temp == null){
System.out.println("Invalid Position");
return;
}
if(temp.next == null){
temp.next = newNode;
newNode.prev = temp;
return;
}
newNode.next = temp.next;
newNode.prev = temp;
temp.next.prev = newNode;
temp.next = newNode;
}
public void display(){
Node temp = head;
while(temp != null){
System.out.print(temp.data + " ⇄ ");
temp = temp.next;
}
System.out.println("NULL");
}
public static void main(String args[]){
DoublyLinkedList list = new DoublyLinkedList();
list.insertAtEnd(10);
list.insertAtEnd(20);
list.insertAtEnd(40);
list.insertAtPosition(3,30);
list.insertAtBeginning(5);
list.display();
}
}
Output
5 ⇄ 10 ⇄ 20 ⇄ 30 ⇄ 40 ⇄ NULL
📊 Time Complexity
| Operation | Time Complexity |
|---|---|
| Insert at Beginning | O(1) |
| Insert at End | O(n)* |
| Insert at Position | O(n) |
Note: If a Tail pointer is maintained, insertion at the end can be performed in O(1) time.
⚠️ Common Mistakes
❌ Forgetting to update prev
newNode.next = temp.next;
But forgetting
temp.next.prev = newNode;
This breaks backward traversal.
❌ Forgetting to update Head
head = newNode;
Without updating the head during insertion at the beginning, the new node will not become the first node.
❌ Not handling an empty list
Always check:
if(head == null)
before accessing head.next or head.prev.
❓ Frequently Asked Questions
Q1. Why are more references updated than in a Singly Linked List?
Because every node stores both a previous and a next reference, both directions must remain consistent.
Q2. Which insertion is the fastest?
Insertion at the beginning, because it only updates a few references and takes O(1) time.
Q3. Can insertion at the end be O(1)?
Yes. If the list maintains a Tail pointer, the last node can be accessed directly.
Q4. How many references are updated when inserting in the middle?
Typically four references are updated:
newNode.nextnewNode.prevprevious.nextnext.prev
Q5. Why is insertion at a specific position O(n)?
Because the list must first be traversed to reach the required position.
🎯 Key Takeaways
- ➕ Insertion adds a new node by updating both next and prev references.
- 🚀 Insertion at the beginning takes O(1) time.
- 🚶 Insertion at the end takes O(n) without a Tail pointer.
- 📍 Insertion at a specific position requires updating four references.
- 🔗 Correctly maintaining both forward and backward links is essential for a valid Doubly Linked List.
🎉 Conclusion
Insertion in a Doubly Linked List is slightly more complex than in a Singly Linked List because every new node must be connected in both directions. However, this extra work provides the major benefit of bidirectional traversal, making many operations more efficient and flexible.
In this part, you learned how to insert nodes at the beginning, end, and any valid position, along with complete Java implementations, dry runs, complexity analysis, and common mistakes to avoid.
👉 In Part 3, we’ll explore Deletion Operations in a Doubly Linked List, including:
- 🗑️ Deletion from the Beginning
- 🗑️ Deletion from the End
- 🗑️ Deletion at a Specific Position
- 🗑️ Deletion by Value
- 💻 Complete Java programs
- 🔍 Detailed dry runs
- 📈 Time complexity analysis
- 🎯 Interview questions