A linked list in C++ is a data structure consisting of nodes where each node contains data and a pointer to the next node, enabling efficient insertion and deletion.
Here’s a simple implementation of a singly linked list in C++:
#include <iostream>
struct Node {
int data;
Node* next;
};
class LinkedList {
private:
Node* head;
public:
LinkedList() : head(nullptr) {}
void insert(int value) {
Node* newNode = new Node{value, head};
head = newNode;
}
void display() {
Node* current = head;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->next;
}
}
};
int main() {
LinkedList list;
list.insert(10);
list.insert(20);
list.display(); // Output: 20 10
return 0;
}
Types of Linked Lists
Singly Linked List
A singly linked list is a data structure that consists of a sequence of nodes, where each node contains two components: the data and a pointer to the next node in the list. This structure allows for dynamic memory allocation and efficient insertions and deletions.
Node Structure
The basic structure of a node in a singly linked list can be defined as follows:
class Node {
public:
int data; // Data part
Node* next; // Pointer to the next node
Node(int val) : data(val), next(nullptr) {}
};
Example of Singly Linked List
Below is an example that illustrates the basic operations, including insertion and deletion.
class SinglyLinkedList {
private:
Node* head;
public:
SinglyLinkedList() : head(nullptr) {}
void insertAtBeginning(int val) {
Node* newNode = new Node(val);
newNode->next = head;
head = newNode;
}
void display() {
Node* current = head;
while (current) {
std::cout << current->data << " -> ";
current = current->next;
}
std::cout << "nullptr" << std::endl;
}
void deleteFirstNode() {
if (!head) return; // List is empty
Node* temp = head;
head = head->next;
delete temp;
}
// Add more operations as needed...
};
Doubly Linked List
A doubly linked list improves upon the singly linked list by allowing traversal in both directions. Each node contains two pointers: one pointing to the next node and one to the previous node.
Node Structure
Here's how a node in a doubly linked list can be structured:
class DoublyNode {
public:
int data; // Data part
DoublyNode* next; // Pointer to the next node
DoublyNode* prev; // Pointer to the previous node
DoublyNode(int val) : data(val), next(nullptr), prev(nullptr) {}
};
Example of Doubly Linked List
This example shows how to implement basic operations:
class DoublyLinkedList {
private:
DoublyNode* head;
public:
DoublyLinkedList() : head(nullptr) {}
void insertAtBeginning(int val) {
DoublyNode* newNode = new DoublyNode(val);
newNode->next = head;
if (head) {
head->prev = newNode;
}
head = newNode;
newNode->prev = nullptr;
}
void display() {
DoublyNode* current = head;
while (current) {
std::cout << current->data << " <=> ";
current = current->next;
}
std::cout << "nullptr" << std::endl;
}
void deleteFirstNode() {
if (!head) return; // List is empty
DoublyNode* temp = head;
head = head->next;
if (head) head->prev = nullptr;
delete temp;
}
// Add more operations as needed...
};
Circular Linked List
In a circular linked list, the last node points back to the first node, creating a circular structure. This allows for continuous traversal without having to reach a null pointer at the end.
Node Structure
The node structure is similar but with a twist:
class CircularNode {
public:
int data; // Data part
CircularNode* next; // Pointer to the next node
CircularNode(int val) : data(val), next(nullptr) {}
};
Example of Circular Linked List
Here's how you can implement a circular linked list:
class CircularLinkedList {
private:
CircularNode* head;
public:
CircularLinkedList() : head(nullptr) {}
void insertAtEnd(int val) {
CircularNode* newNode = new CircularNode(val);
if (!head) {
head = newNode;
newNode->next = head; // Point to itself
} else {
CircularNode* temp = head;
while (temp->next != head) {
temp = temp->next;
}
temp->next = newNode;
newNode->next = head;
}
}
void display() {
if (!head) return; // Empty list
CircularNode* current = head;
do {
std::cout << current->data << " -> ";
current = current->next;
} while (current != head);
std::cout << "(back to head)" << std::endl;
}
// Add more operations as needed...
};

Linked List Implementation in C++
Creating a Linked List in C++
Creating a linked list in C++ involves defining a node structure and managing its memory. The following approach outlines how to create a linked list step-by-step:
-
Initializing the head pointer:
It's essential to start with an empty list where the head pointer is set to null. -
Creating new nodes:
Whenever you insert an element, create a new node allocated with the `new` operator.
Node* newNode = new Node(value);
Basic Operations on Linked List in C++
Insertion
Insertion can be performed at various locations:
Insert at the Beginning:
void insertAtBeginning(int val) {
Node* newNode = new Node(val);
newNode->next = head;
head = newNode;
}
Insert at the End:
void insertAtEnd(int val) {
Node* newNode = new Node(val);
if (!head) {
head = newNode;
} else {
Node* temp = head;
while (temp->next) {
temp = temp->next;
}
temp->next = newNode;
}
}
Insert at a Specific Position:
void insertAtPosition(int val, int position) {
if (position == 0) {
insertAtBeginning(val);
return;
}
Node* newNode = new Node(val);
Node* current = head;
for (int i = 0; current != nullptr && i < position - 1; i++) {
current = current->next;
}
if (current == nullptr) {
std::cout << "Position out of bounds" << std::endl;
delete newNode;
} else {
newNode->next = current->next;
current->next = newNode;
}
}
Deletion
Delete the First Node:
void deleteFirstNode() {
if (!head) return;
Node* temp = head;
head = head->next;
delete temp;
}
Delete the Last Node:
void deleteLastNode() {
if (!head) return;
if (!head->next) {
delete head;
head = nullptr;
return;
}
Node* current = head;
while (current->next->next) {
current = current->next;
}
delete current->next;
current->next = nullptr;
}
Delete a Node at a Specific Position:
void deleteNodeAtPosition(int position) {
if (!head) return; // Empty list
if (position == 0) {
deleteFirstNode();
return;
}
Node* current = head;
for (int i = 0; i < position - 1 && current != nullptr; i++) {
current = current->next;
}
if (current == nullptr || current->next == nullptr) return;
Node* nodeToDelete = current->next;
current->next = nodeToDelete->next;
delete nodeToDelete;
}
Traversal (Display)
Displaying the elements of a linked list is straightforward:
void display() {
Node* current = head;
while (current) {
std::cout << current->data << " -> ";
current = current->next;
}
std::cout << "nullptr" << std::endl;
}

Advanced Linked List Operations
Searching for a Node
Searching through a linked list involves iterating through its nodes until the desired value is found. The function below illustrates this:
bool search(int val) {
Node* current = head;
while (current) {
if (current->data == val) {
return true;
}
current = current->next;
}
return false;
}
Reversing a Linked List
Reversing a linked list is a useful operation that changes the direction of node pointers:
void reverse() {
Node* prev = nullptr;
Node* current = head;
while (current) {
Node* nextNode = current->next; // Store next node
current->next = prev; // Reverse pointer
prev = current; // Move prev to this node
current = nextNode; // Move to next node
}
head = prev; // Update head to the new front
}
Merging Two Linked Lists
Merging two sorted linked lists involves comparing their head nodes and linking them accordingly. Here’s an outline of how to implement this process:
Node* merge(Node* list1, Node* list2) {
if (!list1) return list2;
if (!list2) return list1;
Node* mergedHead = nullptr;
if (list1->data < list2->data) {
mergedHead = list1;
list1 = list1->next;
} else {
mergedHead = list2;
list2 = list2->next;
}
Node* current = mergedHead;
while (list1 && list2) {
if (list1->data < list2->data) {
current->next = list1;
list1 = list1->next;
} else {
current->next = list2;
list2 = list2->next;
}
current = current->next;
}
current->next = (list1) ? list1 : list2;
return mergedHead;
}

C++ Linked List Example
Here is a complete implementation of a singly linked list in C++ encapsulating all functionalities:
class SinglyLinkedList {
private:
Node* head;
public:
SinglyLinkedList() : head(nullptr) {}
void insertAtEnd(int val) {
Node* newNode = new Node(val);
if (!head) {
head = newNode;
} else {
Node* temp = head;
while (temp->next) {
temp = temp->next;
}
temp->next = newNode;
}
}
void deleteFirstNode() {
if (!head) return;
Node* temp = head;
head = head->next;
delete temp;
}
void display() {
Node* current = head;
while (current) {
std::cout << current->data << " -> ";
current = current->next;
}
std::cout << "nullptr" << std::endl;
}
// Add more methods as needed...
};

Best Practices for Linked List Implementation in C++
In terms of best practices for linked list code in C++, consider the following:
- Memory Management: C++ requires you to manage memory carefully; always free dynamically allocated nodes to avoid memory leaks.
- Use of Smart Pointers: Whenever possible, use smart pointers (e.g., `std::unique_ptr` or `std::shared_ptr`) to prevent memory leaks and ensure efficient memory management.
- Choosing the Right Data Structure: Evaluate whether a linked list is genuinely the best choice. In some cases, arrays or vectors may be more efficient, depending on the scenario.

Conclusion
Linked lists play a crucial role in data structure management and are integral to understanding more complex data handling techniques. Practicing linked list code in C++ equips you with the necessary skills to tackle a wide range of programming challenges. Dive into implementing linked lists regularly, and you'll appreciate their elegant solutions to various data organization problems.

Further Reading and Resources
For deeper exploration, consider checking out specialized books on data structures and algorithms, or coding platforms where you can find practice problems tailored to linked lists and their applications. Whether you're pursuing competitive programming or simply solidifying your coding foundation, continued learning and practice are key to mastering linked lists in C++.