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_head
and returns.
- Calls
- Insert at tail (
head->next == NULL
):- Calls
insert_at_tail
and returns.
- Calls
- Traverse to position
p-1
:- Uses
head
pointer and countercnt
. - Loop stops at node before position
p
.
- Uses
- Insert in middle:
- Creates
new_node
withdata
. - Links
new_node->next
tohead->next
. - Updates
head->next
tonew_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;
}