Singly Linked List Tutorial
Last Updated :
21 Apr, 2024
What is Singly Linked List?
A singly linked list is a fundamental data structure in computer science and programming. It is a collection of nodes where each node contains a data field and a reference (link) to the next node in the sequence. The last node in the list points to null, indicating the end of the list. This linear data structure allows for efficient insertion and deletion operations, making it a popular choice for various applications.
Understanding Node Structure:
In a singly linked list, each node consists of two parts: data and a pointer to the next node. The data part stores the actual information, while the pointer (or reference) part stores the address of the next node in the sequence. This structure allows nodes to be dynamically linked together, forming a chain-like sequence.
Singly Linked List
In this representation, each box represents a node, with an arrow indicating the link to the next node. The last node points to NULL, indicating the end of the list.
Node Definition:
In most programming languages, a node in a singly linked list is typically defined using a class or a struct. Here’s an example of a basic node structure in C++:
C++
struct Node {
int data;
Node* next;
};
In this example, the Node struct contains an integer data field (data) to store the information and a pointer to another Node (next) to establish the link to the next node in the list.
Operations on Singly Linked List:
- Traversal
- Searching
- Length
- Insertion:
- Insert at the beginning
- Insert at the end
- Insert at a specific position
- Deletion:
- Delete from the beginning
- Delete from the end
- Delete a specific node
Let’s go through each of the operations mentioned above, one by one.
Traversal in Singly Linked List:
Traversal involves visiting each node in the linked list and performing some operation on the data. A simple traversal function would print or process the data of each node.
Steps for Traversal in Singly Linked List:
- Initialize a pointer current to the head of the list.
- Use a while loop to iterate through the list until the current pointer reaches nullptr.
- Inside the loop, print the data of the current node and move the current pointer to the next node.
Below is the implementation of the above approach:
C++
#include <iostream>
struct Node {
int data;
Node* next;
};
void traverseLinkedList(Node* head) {
// Start from the head of the linked list
Node* current = head;
// Traverse the linked list until reaching the end
// (nullptr)
while (current != nullptr) {
// Print the data of the current node
std::cout << current->data << " ";
// Move to the next node
current = current->next;
}
std::cout << std::endl;
}
Java
// Assuming the Node class is defined as follows:
class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
this.next = null;
}
}
// Function to traverse and print the elements of the linked list
void traverseLinkedList(Node head) {
// Start from the head of the linked list
Node current = head;
// Traverse the linked list until reaching the end (null)
while (current != null) {
// Print the data of the current node
System.out.print(current.data + " ");
// Move to the next node
current = current.next;
}
System.out.println();
}
Searching in Singly Linked List:
Searching in a Singly Linked List refers to the process of looking for a specific element or value within the elements of the linked list.
Steps for Searching in Singly Linked List:
- Initialize a pointer head to the starting node of the Linked List.
- Use a while loop to traverse the Linked List until the end is reached (i.e., head becomes nullptr).
- Inside the loop, check if the current node’s data is equal to the target value.
- If true, return true indicating that the value is found in the Linked List.
- If false, move to the next node by updating head to point to the next node in the list.
- If the loop completes without finding the value, return false indicating that the value is not present in the Linked List.
C++
// Function to search for a value in the Linked List
bool searchLinkedList(Node* head, int target) {
// Traverse the Linked List
while (head != nullptr) {
// Check if the current node's data matches the target value
if (head->data == target) {
return true; // Value found
}
// Move to the next node
head = head->next;
}
return false; // Value not found
}
Steps for finding length in Singly Linked List:
- Initialize a counter variable length to 0.
- Create a pointer current and set it to the head of the linked list.
- Use a while loop to iterate through the linked list:
- Increment the length counter.
- Move the current pointer to the next node in the list.
- After the loop, return the final value of the length variable.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
// Define the Node struct
struct Node {
int data;
Node* next;
};
// Function to find the length of the linked list
int findLength(Node* head) {
// Initialize a counter for the length
int length = 0;
// Start from the head of the list
Node* current = head;
// Traverse the list and increment the length for each node
while (current != nullptr) {
length++;
current = current->next;
}
// Return the final length of the linked list
return length;
}
Insertion is a fundamental operation in linked lists that involves adding a new node to the list. There are several scenarios for insertion:
Insertion at the Beginning of Singly Linked List
Approach:Â
To insert a node at the start/beginning/front of a Linked List, we need to:
- Make the first node of Linked List linked to the new node
- Remove the head from the original first node of Linked List
- Make the new node as the Head of the Linked List.
Below is the implementation of the approach:
C++
// Given a reference (pointer to pointer)
// to the head of a list and an int,
// inserts a new node on the front of
// the list.
void insertionAtBeginning(Node** head_ref, int new_data)
{
// 1. Allocate node
Node* new_node = new Node();
// 2. Put in the data
new_node->data = new_data;
// 3. Make next of new node as head
new_node->next = (*head_ref);
// 4. Move the head to point to
// the new node
(*head_ref) = new_node;
}
C
/* Given a reference (pointer to pointer) to the head of a
list
and an int, inserts a new node on the front of the list.
*/
void push(struct Node** head_ref, int new_data)
{
/* 1. allocate node */
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
/* 2. put in the data */
new_node->data = new_data;
/* 3. Make next of new node as head */
new_node->next = (*head_ref);
/* 4. move the head to point to the new node */
(*head_ref) = new_node;
}
Java
/* This function is in LinkedList class. Inserts a
new Node at front of the list. This method is
defined inside LinkedList class shown above */
public void push(int new_data)
{
/* 1 & 2: Allocate the Node &
Put in the data*/
Node new_node = new Node(new_data);
/* 3. Make next of new Node as head */
new_node.next = head;
/* 4. Move the head to point to new Node */
head = new_node;
}
Python
# This function is in LinkedList class
# Function to insert a new node at the beginning
def push(self, new_data):
# 1 & 2: Allocate the Node &
# Put in the data
new_node = Node(new_data)
# 3. Make next of new Node as head
new_node.next = self.head
# 4. Move the head to point to new Node
self.head = new_node
C#
/* Inserts a new Node at front of the list. */
public void push(int new_data)
{
/* 1 & 2: Allocate the Node &
Put in the data*/
Node new_node = new Node(new_data);
/* 3. Make next of new Node as head */
new_node.next = head;
/* 4. Move the head to point to new Node */
head = new_node;
}
Javascript
/* This function is in LinkedList class. Inserts a
new Node at front of the list. This method is
defined inside LinkedList class shown above */
function push(new_data) {
/* 1 & 2: Allocate the Node & Put in the data*/
var new_node = new Node(new_data);
/* 3. Make next of new Node as head */
new_node.next = head;
/* 4. Move the head to point to new Node */
head = new_node;
}
To insert a node at the end of the list, traverse the list until the last node is reached, and then link the new node to the current last node.-
Insertion at the End of Singly Linked List
Approach:Â
To insert a node at the end of a Linked List, we need to:
- Go to the last node of the Linked List
- Change the next pointer of last node from NULL to the new node
- Make the next pointer of new node as NULL to show the end of Linked List
Below is the implementation of the approach:
C++
// Given a reference (pointer to pointer) to the head
// of a list and an int, appends a new node at the end
void insertionAtEnd(Node** head_ref, int new_data)
{
// 1. allocate node
Node* new_node = new Node(new_data);
// Used in step 5
Node* last = *head_ref;
// 2. If the Linked List is empty,
// then make the new node as head
if (*head_ref == nullptr) {
*head_ref = new_node;
return;
}
// 3. Else traverse till the last node
while (last->next != nullptr) {
last = last->next;
}
// 4. Change the next of last node
last->next = new_node;
}
C
/* Given a reference (pointer to pointer) to the head
of a list and an int, appends a new node at the end */
void append(struct Node** head_ref, int new_data)
{
/* 1. allocate node */
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
struct Node* last = *head_ref; /* used in step 5*/
/* 2. put in the data */
new_node->data = new_data;
/* 3. This new node is going to be the last node, so
make next of it as NULL*/
new_node->next = NULL;
/* 4. If the Linked List is empty, then make the new
* node as head */
if (*head_ref == NULL) {
*head_ref = new_node;
return;
}
/* 5. Else traverse till the last node */
while (last->next != NULL)
last = last->next;
/* 6. Change the next of last node */
last->next = new_node;
return;
}
Java
/* Appends a new node at the end. This method is
defined inside LinkedList class shown above */
public void append(int new_data) {
/* 1. Allocate the Node &
2. Put in the data
3. Set next as null */
Node new_node = new Node(new_data);
/* 4. If the Linked List is empty, then make the
new node as head */
if (head == null) {
head = new Node(new_data);
return;
}
/* 5. This new node is going to be the last node, so
make next of it as null */
new_node.next = null;
/* 6. Else traverse till the last node */
Node last = head;
while (last.next != null)
last = last.next;
/* 7. Change the next of last node */
last.next = new_node;
return;
}
Python
# This function is defined in Linked List class
# Appends a new node at the end. This method is
# defined inside LinkedList class shown above
def append(self, new_data):
# 1. Create a new node
# 2. Put in the data
# 3. Set next as None
new_node = Node(new_data)
# 4. If the Linked List is empty, then make the
# new node as head
if self.head is None:
self.head = new_node
return
# 5. Else traverse till the last node
last = self.head
while (last.next):
last = last.next
# 6. Change the next of last node
last.next = new_node
C#
/* Appends a new node at the end. This method is
defined inside LinkedList class shown above */
public void append(int new_data)
{
/* 1. Allocate the Node &
2. Put in the data
3. Set next as null */
Node new_node = new Node(new_data);
/* 4. If the Linked List is empty,
then make the new node as head */
if (head == null) {
head = new Node(new_data);
return;
}
/* 4. This new node is going to be
the last node, so make next of it as null */
new_node.next = null;
/* 5. Else traverse till the last node */
Node last = head;
while (last.next != null)
last = last.next;
/* 6. Change the next of last node */
last.next = new_node;
return;
}
Javascript
/* Appends a new node at the end. This method is
defined inside LinkedList class shown above */
function append(new_data)
{
/* 1. Allocate the Node &
2. Put in the data
3. Set next as null */
var new_node = new Node(new_data);
/* 4. If the Linked List is empty, then make the
new node as head */
if (head == null)
{
head = new Node(new_data);
return;
}
/* 4. This new node is going to be the last node, so
make next of it as null */
new_node.next = null;
/* 5. Else traverse till the last node */
var last = head;
while (last.next != null)
last = last.next;
/* 6. Change the next of last node */
last.next = new_node;
return;
}
To insert a node at a specific position, traverse the list to the desired position, link the new node to the next node, and update the links accordingly.
Insertion at a Specific Position of the Singly Linked List
Steps-by-step approach:
- Create a new node (newNode) with the given value.
- Check if the position is 0 or if the list is empty (head == nullptr).
- If true, set newNode->next to the current head, and update head to newNode. The insertion is done at the beginning.
- Return from the function.
- If the position is not at the beginning:
- Initialize a pointer current to the head of the list.
- Traverse the list until reaching the node just before the specified position.
- Move current to the next node in each iteration until position – 1 or the end of the list is reached.
- Insert the newNode at the specified position:
- Set newNode->next to current->next.
- Update current->next to newNode.
Below is the implementation of the approach:
C++
#include <iostream>
struct Node {
int data;
Node* next;
Node(int value) : data(value), next(nullptr) {}
};
Node* head = nullptr; // assuming head is a global variable
void insertAtPosition(int value, int position) {
// Create a new node with the given data
Node* newNode = new Node(value);
// If position is 0 or the list is empty, insert at the beginning
if (position == 0 || head == nullptr) {
newNode->next = head;
head = newNode;
return;
}
// Traverse to the node just before the specified position
Node* current = head;
for (int i = 1; i < position && current->next != nullptr; ++i) {
current = current->next;
}
// Insert the new node at the specified position
newNode->next = current->next;
current->next = newNode;
}
// Example usage:
// insertAtPosition(5, 2); // Inserts value 5 at position 2
Java
// Assuming the Node class is defined like this:
class Node {
public int data;
public Node next;
public Node(int value) {
this.data = value;
this.next = null;
}
}
// Declare the head pointer globally
Node head = null;
// Function to insert a new node at a specific position in the list
void insertAtPosition(int value, int position) {
// Create a new node with the given data
Node newNode = new Node(value);
// If position is 0 or the list is empty, insert at the beginning
if (position == 0 || head == null) {
newNode.next = head;
head = newNode;
return;
}
// Traverse to the node just before the specified position
Node current = head;
for (int i = 1; i < position && current.next != null; ++i) {
current = current.next;
}
// Insert the new node at the specified position
newNode.next = current.next;
current.next = newNode;
}
Python3
# Class to represent a node
class Node:
def __init__(self, value):
self.value = value
self.next = None
# Function to insert a new node at a specific position in the list
def insertAtPosition(head, value, position):
# Create a new node with the given data
newNode = Node(value)
# If position is 0 or the list is empty, insert at the beginning
if position == 0 or head is None:
newNode.next = head
head = newNode
return head
# Traverse to the node just before the specified position
current = head
for i in range(1, position):
if current.next is None:
break
current = current.next
# Insert the new node at the specified position
newNode.next = current.next
current.next = newNode
return head
JavaScript
// Assuming the Node class is defined like this:
class Node {
constructor(value) {
this.data = value;
this.next = null;
}
}
// Declare the head pointer globally
let head = null;
// Function to insert a new node at a specific position in the list
function insertAtPosition(value, position) {
// Create a new node with the given data
let newNode = new Node(value);
// If position is 0 or the list is empty, insert at the beginning
if (position === 0 || head === null) {
newNode.next = head;
head = newNode;
return;
}
// Traverse to the node just before the specified position
let current = head;
for (let i = 1; i < position && current.next !== null; ++i) {
current = current.next;
}
// Insert the new node at the specified position
newNode.next = current.next;
current.next = newNode;
}
Deletion involves removing a node from the linked list. Similar to insertion, there are different scenarios for deletion:
To delete the first node, update the head to point to the second node in the list.
Deletion at the Beginning of Singly Linked List
Steps-by-step approach:
- Check if the linked list is empty (head == nullptr).
- If the list is empty, print a message indicating that the list is empty, and return without performing any deletion.
- If the list is not empty:
- Store the current head node in a temporary variable (Node* temp = head).
- Update the head to point to the next node (head = head->next).
- Delete the old head node using delete temp
Below is the implementation of the approach:
C++
#include <iostream>
struct Node {
int data;
Node* next;
};
Node* head = nullptr; // assuming head is a global variable
void deleteAtBeginning() {
// If the list is empty, do nothing
if (head == nullptr) {
std::cout << "List is empty. Cannot delete from the beginning." << std::endl;
return;
}
// Store the current head in a temporary variable
Node* temp = head;
// Update the head to the next node
head = head->next;
// Delete the old head node
delete temp;
}
To delete the last node, traverse the list until the second-to-last node and update its next field to None.
Deletion at the End of Singly Linked List
Below is the implementation of the approach:
C++
#include <iostream>
struct Node {
int data;
Node* next;
};
Node* head = nullptr; // assuming head is a global variable
void deleteAtEnd() {
// If the list is empty, do nothing
if (head == nullptr) {
std::cout << "List is empty. Cannot delete from the end." << std::endl;
return;
}
// If there is only one node, delete it and set head to null
if (head->next == nullptr) {
delete head;
head = nullptr;
return;
}
// Traverse to the second last node
Node* current = head;
while (current->next->next != nullptr) {
current = current->next;
}
// Delete the last node
delete current->next;
current->next = nullptr;
}
To delete a node at a specific position, traverse the list to the desired position, update the links to bypass the node to be deleted.
Deletion at a Specific Position of Singly Linked List
Below is the implementation of the approach:
C++
void deleteAtPosition(int position)
{
// If the list is empty, do nothing
if (head == nullptr) {
cout << "List is empty. Cannot delete from a "
"specific position."
<< endl;
return;
}
// If deleting the head node
if (position == 0) {
Node* temp = head;
head = head->next;
delete temp;
return;
}
// Traverse to the node just before the specified
// position
Node* current = head;
for (int i = 1;
i < position && current->next != nullptr; ++i) {
current = current->next;
}
// If position is beyond the end of the list, do nothing
if (current->next == nullptr) {
cout << "Position is beyond the end of the list. "
"Cannot delete."
<< endl;
}
else {
// Delete the node at the specified position
Node* temp = current->next;
current->next = current->next->next;
delete temp;
}
}
Java
// Define a class named GFG
public class GFG {
// Define a Node class for the linked list
static class Node {
int data; // Data stored in the node
Node next; // Pointer to the next node
// Constructor to initialize node with given value
Node(int val) {
data = val;
next = null;
}
}
// Define the deleteAtPosition method
public static void deleteAtPosition(Node head, int position) {
// If the list is empty, do nothing
if (head == null) {
System.out.println("List is empty. Cannot delete from a specific position.");
return;
}
// If deleting the head node
if (position == 0) {
Node temp = head;
head = head.next;
temp = null; // Free memory by making the node eligible for garbage collection
return;
}
// Traverse to the node just before the specified position
Node current = head;
for (int i = 1; i < position && current.next != null; ++i) {
current = current.next;
}
// If position is beyond the end of the list, do nothing
if (current.next == null) {
System.out.println("Position is beyond the end of the list. Cannot delete.");
} else {
// Delete the node at the specified position
Node temp = current.next;
current.next = current.next.next;
temp = null; // Free memory by making the node eligible for garbage collection
}
}
}
Python3
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def deleteAtPosition(self, position):
# If the list is empty, do nothing
if self.head is None:
print("List is empty. Cannot delete from a specific position.")
return
# If deleting the head node
if position == 0:
temp = self.head
self.head = self.head.next
del temp
return
# Traverse to the node just before the specified position
current = self.head
for i in range(1, position):
if current.next is None:
break
current = current.next
# If position is beyond the end of the list, do nothing
if current.next is None:
print("Position is beyond the end of the list. Cannot delete.")
else:
# Delete the node at the specified position
temp = current.next
current.next = current.next.next
del temp
JavaScript
function deleteAtPosition(position) {
// If the list is empty, do nothing
if (!head) {
console.log("List is empty. Cannot delete from a specific position.");
return;
}
// If deleting the head node
if (position === 0) {
let temp = head;
head = head.next;
temp = null; // Clearing memory
return;
}
// Traverse to the node just before the specified position
let current = head;
let prev = null;
for (let i = 0; i < position && current.next !== null; ++i) {
prev = current;
current = current.next;
}
// If position is beyond the end of the list, do nothing
if (current === null) {
console.log("Position is beyond the end of the list. Cannot delete.");
return;
}
// Delete the node at the specified position
prev.next = current.next;
current = null; // Clearing memory
}
Share your thoughts in the comments
Please Login to comment...