Linked List
A linked list is a linear data structure where each element (node) contains a value and a reference to the next node in the sequence. It allows efficient insertions and deletions but slower access compared to arrays, as elements are not stored in contiguous memory.
Singly Linked List
In a singly linked list, each node consists of two parts: data and a pointer to the next node. This structure allows nodes to be dynamically linked together, forming a chain-like sequence.
Representation
1
2
3
4
5
6
7
8
9
10
class Node{
public:
int data;
Node* next = NULL;
Node(int data)
{
this->data = data;
}
};
Purpose: Defines the structure of a node in a singly linked list.
Explanation:
data: Stores the value of the node.next: Pointer to the next node in the list.- Constructor initializes the data field and sets next to
NULL.
Traversal (Iterative Approach)
1
2
3
4
5
6
7
8
void print_linked_list(Node* head)
{
while(head!=NULL)
{
cout << head->data << " ";
head = head->next;
}
}
Traversal (Recursive Approach)
1
2
3
4
5
6
7
8
9
void traverse_recursive(Node* head)
{
if(head == NULL)
{
return;
}
cout << head->data << " ";
traverse_recursive(head->next);
}
Insert at Head
1
2
3
4
5
6
void insert_at_head(Node* &head, int data)
{
Node* temp = new Node(data);
temp->next = head;
head = temp;
}
Insert at Tail
1
2
3
4
5
6
void insert_at_tail(Node* &tail, int data)
{
Node* temp = new Node(data);
tail->next = temp;
tail = temp;
}
Insert at Position
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void insert_at_position(Node* &node, int data, int p, Node* &tail)
{
if(p==1)
{
insert_at_head(node, data);
return;
}
Node* head = node;
int cnt=1;
while(cnt<p-1)
{
head = head->next;
cnt++;
}
if(head->next == NULL)
{
insert_at_tail(tail, data);
return;
}
Node* new_node = new Node(data);
new_node->next = head->next;
head->next = new_node;
}
Purpose: Inserts a node with data at position p in a linked list.
Explanation:
- Insert at head (
p == 1):- Calls
insert_at_headand returns.
- Calls
- Insert at tail (
head->next == NULL):- Calls
insert_at_tailand returns.
- Calls
- Traverse to position
p-1:- Uses
headpointer and countercnt. - Loop stops at node before position
p.
- Uses
- Insert in middle:
- Creates
new_nodewithdata. - Links
new_node->nexttohead->next. - Updates
head->nexttonew_node.
- Creates
Edge Cases: Handles head, tail, and middle insertions.
Delete Node (Any Position)
Destructor (~Node())
Ensures memory is cleaned up properly:
- If the current node points to another node
(next != NULL), it deletes the next node recursively. - This helps prevent memory leaks when deleting a chain of nodes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Node{
public:
int data;
Node* next = NULL;
Node(int data)
{
this->data = data;
}
~Node()
{
if(this->next != NULL)
{
delete next;
this->next = NULL;
}
}
};
Destructor is an instance member function that is invoked automatically whenever an object is going to be destroyed. Meaning, a destructor is the last function that is going to be called before an object is destroyed.
Delete Node Function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void delete_node(int position, Node* &head, Node* &tail)
{
if(position == 1)
{
Node* temp = head;
head = head->next;
temp->next = NULL;
delete temp;
}
else
{
Node* current = head;
Node* pre = NULL;
int cnt = 1;
while(cnt<position)
{
pre = current;
current = current->next;
cnt++;
}
if(current->next == NULL)
{
tail=pre;
}
pre->next = current->next;
current->next = NULL;
delete current;
}
}
Purpose: Deletes a node at a given position from a singly linked list.
Explanation:
- position == 1:
- Deletes the head node. Updates head to the next node and frees memory.
- Else:
- Traverses to the node at the given position.
- Updates the next pointer of the previous node to skip the current node.
- If deleting the last node, updates tail.
- Frees the memory of the deleted node.
Full Code: Singly Linked List
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include<bits/stdc++.h>
using namespace std;
// Node class for singly linked list
class Node {
public:
int data;
Node* next = NULL;
Node(int data) {
this->data = data;
}
// Recursively delete entire list from this node
~Node() {
if(this->next != NULL) {
delete next;
this->next = NULL;
}
}
};
// Insert new node at head
void insert_at_head(Node* &head, int data) {
Node* temp = new Node(data);
temp->next = head;
head = temp;
}
// Insert new node at tail
void insert_at_tail(Node* &tail, int data) {
Node* temp = new Node(data);
tail->next = temp;
tail = temp;
}
// Insert new node at given position (1-based)
void insert_at_position(Node* &node, int data, int p, Node* &tail) {
if(p==1) {
insert_at_head(node, data);
return;
}
Node* head = node;
int cnt=1;
while(cnt < p-1) {
head = head->next;
cnt++;
}
if(head->next == NULL) {
insert_at_tail(tail, data);
return;
}
Node* new_node = new Node(data);
new_node->next = head->next;
head->next = new_node;
}
// Print linked list (iteratively)
void print_linked_list(Node* head) {
while(head != NULL) {
cout << head->data << " ";
head = head->next;
}
}
// Print linked list (recursively)
void traverse_recursive(Node* head) {
if(head == NULL) return;
cout << head->data << " ";
traverse_recursive(head->next);
}
// Delete node at given position (1-based)
void delete_node(int position, Node* &head, Node* &tail) {
if(position == 1) {
Node* temp = head;
head = head->next;
temp->next = NULL;
delete temp;
} else {
Node* current = head;
Node* pre = NULL;
int cnt = 1;
while(cnt < position) {
pre = current;
current = current->next;
cnt++;
}
if(current->next == NULL) tail = pre;
pre->next = current->next;
current->next = NULL;
delete current;
}
}
int main() {
// Create initial node
Node* node = new Node(0);
Node* head = node;
Node* tail = node;
// Insertions
insert_at_head(head, 10); // 10 -> 0
insert_at_head(head, 5); // 5 -> 10 -> 0
insert_at_tail(tail, 20); // ... -> 0 -> 20
insert_at_tail(tail, 30); // ... -> 20 -> 30
insert_at_position(head, 15, 3, tail); // Insert 15 at pos 3
// Print list
cout << "Linked List (Iterative): ";
print_linked_list(head);
cout << endl;
// Delete 4th node
delete_node(4, head, tail);
// Print list after deletion
cout << "After deletion at position 4: ";
print_linked_list(head);
cout << endl;
// Print list recursively
cout << "Linked List (Recursive): ";
traverse_recursive(head);
cout << endl;
// Print head and tail values
cout << "Head: " << (head ? head->data : -1) << endl;
cout << "Tail: " << (tail ? tail->data : -1) << endl;
// Clean memory (deletes entire list from head)
delete head;
return 0;
}