1. Home
Data Structure

Data Structure Tutorial: Everything You Need to Know

Learn all about data structures with our comprehensive tutorial. Master the fundamentals and advance your skills in organizing and managing data efficiently.

  • 60
  • 14
right-top-arrow

Tutorial Playlist

58 Lessons
5

Understanding Singly Linked Lists: A Comprehensive Guide

Updated on 25/07/2024452 Views

Introduction

A singly linked list is a dynamic and flexible data structure that allows you to store elements in a non-contiguous manner with each element linked to the next via pointers. This means that you can easily add or remove elements without the constraints of fixed memory allocation.

The concept of singly linked lists dates back to the earliest days of computers. It has developed throughout time and is now used in a variety of disciplines, including computer languages and database systems.

Nearly every major programming language, including Python, Java, and C++, has its implementation of singly linked lists. Singly-linked lists are integral components of modern computing, powering everything from basic algorithms to complex data structures.

In this article, I will explain singly linked lists in detail. We will discuss its implementation, operations, and much more.

Overview

A singly linked list is a type of linked list that acts like a chain of connected elements, known as nodes, where each node contains both data and a pointer to the next node in the sequence. This unidirectional structure means you can traverse the list from the starting point, called the head and all the way to the end, known as the tail.

Nodes in a singly linked list data structure hold valuable information, along with a reference to the next node, ensuring the continuity of the sequence. The head serves as the entry point, providing access to the first node, while the tail signifies the end of the list, pointing to NULL.

By the end of this guide, you will understand singly linked lists and how they work. You will also learn how to perform operations like delete and insert on singly linked lists.

What is a Singly Linked List?

A singly linked list is a foundational data structure in computer science and programming that plays an important role in managing and organizing data.

A singly linked list is a collection of nodes, where each node contains two components: data and a reference (or pointer) to the next node in the sequence. This structure forms a linear chain, with each node pointing to the next until the end of the list is reached. This sequential arrangement facilitates quick and easy traversal from one node to another.

Singly-linked lists offer flexibility and efficiency in managing dynamic collections of data. One common type of singly linked list is the circular singly linked list. In a circular singly linked list, the last node of the list is linked to the first node of the list, creating a circular structure.

Let's break down the anatomy of a node in a singly linked list:

  • Data: The data part of a node stores the actual information or payload. For example, in a to-do list application, the data might represent the tasks to be completed, such as ‘Buy groceries’ or ‘Finish report’.
  • Pointer: The pointer, also known as the reference or link, holds the memory address of the next node in the sequence.

Time and Space Complexity in Singly Linked Lists

In a singly linked list, the space complexity scales linearly with the number of nodes, resulting in O(n) space complexity as each node contains a reference to the next node. Furthermore, the time complexity for inserting and deleting an element from the list is also O(n) due to the need to traverse the list to locate the appropriate position.

In a singly linked list, accessing elements, as well as insertion at the beginning and end, generally requires traversing the list, resulting in a time complexity of O(n). However, the space complexity remains constant at O(1) regardless of the number of elements in the list.

Operation

Time Complexity (Singly Linked List)

Space Complexity

Accessing by Index

O(n)

O(1)

Insertion at Beginning

O(1)

O(1)

Insertion at End

O(n)

O(1)

Insertion at Given Position

O(n)

O(1)

Implementing Singly Linked List in Python Programming Language

In programming, implementing a singly linked list often involves defining a node class or struct to encapsulate the node's properties. Let's illustrate this with a simple python example: To create a singly linked list in python use the following code

class Node:

def __init__(self, data):

self.data = data

self.next = None

# Example usage

node1 = Node(10)

node2 = Node(20)

node3 = Node(30)

node1.next = node2

node2.next = node3

The singly linked list nodes

class Node:

def __init__(self, data):

self.data = data

self.next = None

In this example, we define a Node class with two attributes: data and next. We then create instances of the Node class and link them together to form a singly linked list.

Operations That Can be Performed on Singly Linked Lists

Singly linked lists offer a variety of operations to manage and manipulate data they contain. These operations help you to interact with singly linked lists. Here are the operations:

  • Traversal
  • Searching
  • Finding Length
  • Insertion
  • Deletion
  • Reversing

Here are the time and space complexity for each operation:

Operation

Time Complexity (TC)

Space Complexity (SC)

Traversing

O(n)

O(1)

Searching

O(n)

O(1)

Finding

O(n)

O(1)

Insertion

O(1)

O(1)

Deletion

O(1)

O(1)

Reversing

O(n)

O(1)

Let's discuss each of these operations in detail.

1. Traversal in Singly Linked List

Traversal is the process of visiting each node in the linked list sequentially and performing some operation on the data contained within each node. This operation could involve printing the data, searching for specific values, or performing calculations.

To traverse a singly linked list, you can follow these steps:

  • Initialize a pointer, let's call it current, to the head of the list.
  • Use a while loop to iterate through the list until the current pointer reaches the end of the list
  • Inside the loop, perform the desired operation on the data of the current node.
  • Move the current pointer to the next node in the sequence.

Here's a simple example of traversing a singly linked list in Python:

class Node:

def __init__(self, data):

self.data = data

self.next = None

# Function to traverse the linked list and print data of each node

def traverse_linked_list(head):

current = head

while current is not None:

print(current.data)

current = current.next

# Example usage

node1 = Node(10)

node2 = Node(20)

node3 = Node(30)

# Linking the nodes together

node1.next = node2

node2.next = node3

# Traverse the linked list

traverse_linked_list(node1)

2. Searching in Singly Linked List

In a singly linked list data structure, searching is identifying a certain element or value among the linked list's elements. Here are the steps to perform searching in a singly linked list:

  • Initialize a pointer, let's call it 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 data of the current node is equal to the target value.
  • If true, return true, indicating that the value is contained within the linked list.
  • If false, update the head to point to the next node in the list.
  • If the loop fails to discover the value, return false, indicating that the value does not exist in the linked list.

Here's an implementation of the search operation in Java:

public class Node {

int data;

Node next;

Node(int data) {

this.data = data;

this.next = null;

}

}

public class SinglyLinkedList {

// search for a value inside the Linked List

public boolean searchLinkedList(Node head, int target) {

// Traverse the Linked List

while (head != null) {

// Check the node's target value

if (head.data == target) {

return true; // Value found

}

// Move to the next node

head = head.next;

}

return false; // Value not found

}

}

3. Finding Length in Singly Linked List

Finding the length of a singly linked list involves determining the number of nodes present in the list. It is similar to counting the number of books on a shelf. You need to go through each book and keep track of how many you have counted. Here are the steps to find the length of a singly linked list:

  • Initialize a counter variable, let's call it length, to 0.
  • Create a pointer, let's call it current, and set it to the head of the linked list.
  • To loop across the linked list, use a while loop.
  • Increment the length counter.
  • Proceed to the following node in the list with the current pointer.
  • After the loop, return the final value of the length variable.

Here is an example in data structure on the implementation of finding the length of a singly linked list in Java:

public class SinglyLinkedList {

// Function to find the length of the linked list

public int findLength(Node head) {

// start counter

int length = 0;

// Start it from the head

Node current = head;

// Traverse the list and increment the length for each node

while (current != null) {

length++;

current = current.next;

}

// Return the final length of the linked list

return length;

}

}

4. Insertion in Singly Linked List

Insertion is a key operation in linked lists, allowing you to add new nodes to the list. Here is the

insertion algorithm for singly linked list in data structure

If PTR is NULL, write "OVERFLOW" and exit.

Set NEW_NODE to PTR.

Set PTR to PTR's next node.

Set NEW_NODE's data to VAL.

Set NEW_NODE's next node to HEAD.

Set HEAD to NEW_NODE.

Exit.

Let's discuss three common scenarios for insertion:

(a) Insertion at the Start of the Singly Linked List:

To insert a node at the beginning, follow these steps:

  • Create a new node with the provided data.
  • Link the new node to the current head of the list.
  • To point to the new node, update the list's head.

Here is an example on how you can implement this in Java:

public class LinkedList {

private Node head;

public void insertAtBeginning(int newData) {

Node newNode = new Node(newData); // Create a new node

newNode.next = head; // Link the new node to the current head

head = newNode; // Update the head to the new node

}

}

(b) Singly Linked List Insertion at the End

To insert a node at the end, you need to:

  • Create a new node with the provided data.
  • Put the new node at the top of the list if it is empty.
  • If not, go through the list until the final node.
  • Link the new node to the last node's next pointer.
  • Assign null to the new node's next pointer.

In Java, it is implemented as follows:

public class LinkedList {

private Node head;

public void insertAtEnd(int newData) {

Node newNode = new Node(newData); // Create a new node

if (head == null) { // If the list is empty

head = newNode; // Make the new node the head

return;

}

Node last = head;

while (last.next != null) {

last = last.next; // Traverse until the last node

}

last.next = newNode; // Link the new node to the last node

}

}

(c) Insertion into the Singly Linked List at a Particular Position:

To insert a node at a specific position, follow these steps:

  • Create a new node with the provided data.
  • Go through the list until you get to the node that comes right before the designated spot.

Insert the new node at the specified position by updating the links accordingly.

5. Deletion in Singly Linked List

Deleting a node from a linked list is another fundamental operation and it involves removing a specific node from the list. Like insertion and deletion may occur in a variety of ways.

(a) Deletion at the Start of a Single-Linked List

To delete the first node, you simply need to update the head of the list to point to the second node. This is how you can use Java to do it:

public class LinkedList {

private Node head;

// Method to delete a node at the beginning of the list

public void deleteAtBeginning() {

if (head == null) { // If the list is empty

System.out.println("List is empty. Cannot delete from the beginning.");

return;

}

Node temp = head; // Store the current head in a temporary variable

head = head.next; // Update it’s head

temp = null; // Delete the old head node

}

}

(b) Singly Linked List Deletion at the End

To delete the last node, you need to traverse the list until the second-to-last node and update its next field to null. Here is its Java implementation:

public class LinkedList {

private Node head;

// Method to delete a node at the end of the list

public void deleteAtEnd() {

if (head == null) { // If the list is empty

System.out.println("List is empty. Cannot delete from the end.");

return;

}

if (head.next == null) { // If there is only one node

head = null;

return;

}

Node current = head;

while (current.next.next != null) { // Traverse to the second-to-last node

current = current.next;

}

current.next = null; // Delete the last node

}

}

(c) Deletion at a Particular Point in a Single-Linked List:

To delete a node at a specific position, you traverse the list to the desired position and update the links to bypass the node to be deleted.

6. Reversing a Singly Linked List

Reversing a singly linked list involves changing the direction of pointers so that the last node becomes the first node and vice versa. This operation is essential for various applications, such as efficiently traversing the list in reverse order or solving certain algorithmic problems.

To reverse a singly linked list, you typically iterate through the list while maintaining references to the previous, current, and next nodes. You update the next pointer of each node to point to its previous node, effectively reversing the direction of the list.

Let's explore the Python code to implement this:

class Node:

def __init__(self, data):

self.data = data

self.next = None

class LinkedList:

def __init__(self):

self.head = None

def reverse(self):

prev_node = None

current_node = self.head

while current_node:

next_node = current_node.next # Store the next node

current_node.next = prev_node # Reverse the pointer

prev_node = current_node # Move prev_node to current_node

current_node = next_node # Move current_node to next_node

self.head = prev_node # Update the head to the last node (prev_node)

def print_list(self):

current_node = self.head

while current_node:

print(current_node.data, end=" ")

current_node = current_node.next

print()

# Example usage

linked_list = LinkedList()

linked_list.head = Node(1)

second_node = Node(2)

third_node = Node(3)

linked_list.head.next = second_node

second_node.next = third_node

print("Original Linked List:")

linked_list.print_list()

linked_list.reverse()

print("Reversed Linked List:")

linked_list.print_list()

In this implementation, we define a Node class to represent each node in the linked list and a LinkedList class to manage the list. The reverse method of the LinkedList class iterates through the list, reversing the pointers of each node. Finally, we demonstrate the reversal operation with an example usage.

Comparing Singly Linked List with Other Data Structures (Doubly Linked Lists and Arrays)

Commonly used data structures like singly linked lists and doubly linked lists offer different features and efficiencies, each suited to specific use cases. Additionally, arrays provide a more traditional data storage option with distinct advantages and limitations. Let’s compare them.

Comparison

Singly Linked List

Doubly Linked List

Arrays

Memory Usage

Requires less memory as it only stores a next pointer for each node.

Requires more memory as it stores both next and previous pointers for each node.

Memory usage depends on the size of the array and the sorted data type.

Insertion/Deletion Efficiency

Efficient for insertion and deletion at the beginning and end of the list.

Efficient for insertion and deletion at any position in the list.

Efficient for random access insertion and deletion, but less efficient for insertion and deletion in the middle.

Traversal Efficiency

Traversal is efficient in a forward direction.

Traversal is efficient in both forward and backward directions.

Traversal is efficient, especially for sequential access.

Flexibility in Operations

Limited flexibility due to unidirectional links.

More flexible due to bidirectional links, allowing efficient backward traversal and manipulation.

Offers flexibility in various operations, including insertion, deletion, and access.

Usage

Suitable for scenarios where forward traversal and efficient insertion/deletion at the beginning or end are frequent operations.

Suitable for scenarios requiring frequent traversal in both forward and backward directions and efficient insertion/deletion at any position.

Suitable for scenarios requiring random access and efficient insertion/deletion at any position.

Real-World Applications and Use Cases of Singly Linked List

Singly linked lists find applications in various real-world scenarios across different domains. Here is a brief discussion of some common singly linked list applications and use cases:


1. Memory Management

Memory management systems frequently use singly linked lists. For example, operating systems use linked lists to manage dynamic memory allocation and deallocation, such as maintaining lists of free memory blocks and allocating memory to processes.

2. Task Management

To manage tasks in applications like to-do lists or task schedulers, singly linked lists offer flexibility in adding, removing, and updating tasks. Each task can be represented as a node in the list, allowing you to efficiently organize and manipulate tasks.

3. Navigation Systems

Navigation systems show pathways or routes using singly linked lists. Each node in the list can represent a location or waypoint and the links between nodes define the sequence of locations to traverse. This application is particularly useful in GPS navigation systems.

4. Undo/Redo Functionality

Many software applications, such as text editors or graphic design tools, implement undo/redo functionality using singly linked lists. Each action performed by the user, such as typing a character or drawing a shape, is recorded as a node in the list. Users can then undo or redo actions by traversing backward or forward through the list.

5. Queue Management in Operating Systems

Singly linked lists are used in operating systems to implement queues for managing tasks or processes. For example, the job scheduling subsystem of an operating system may use a singly linked list to maintain a queue of processes waiting to be executed.

Final Words!

In conclusion, singly linked lists serve as essential data structures with versatile applications across various domains. They provide efficient memory management solutions, facilitate task organization, power navigation systems, and enable undo/redo functionality in software applications. Singly linked lists also support queue management in operating systems.

Therefore, with their simplicity and flexibility, there is no doubt that singly linked lists continue to play a crucial role in modern computing, offering effective solutions for dynamic data management needs

Frequently Asked Questions (FAQs)

  1. What is a Singly and Doubly Linked List?

    A singly linked list is a linear collection of nodes where each node points to the next node in the sequence. In contrast, a doubly linked list is similar but each node points to both the next and previous nodes.
  2. What are the 4 types of linked lists?

    The four main types of linked lists are:
  • Singly-linked List
  • Doubly linked List
  • Circular linked List
  • Doubly Circular Linked List
  1. What is a Singly Headed Linked List?

    A singly-headed linked list is a type of singly linked list where you only have a reference to the head node, allowing traversal only in one direction, typically from the head to the tail.
  2. What are the two parts of a Singly Linked List?

    The two parts of a singly linked list are:
  • Data: Each node contains the actual data or value.
  • Pointer: Every node in the series has a reference to the node after it.
  1. Why is it called a Doubly Linked List?

    A Doubly Linked List is called so because each node in the list contains two pointers: one pointing to the next node and another pointing to the previous node in the sequence.
  2. What is a Doubly Linked List?

    A Doubly Linked List is a type of linked list where each node has references to both the next and previous nodes, allowing traversal in both forward and backward directions.
  3. Where is the Doubly Linked List used?

    Doubly Linked Lists are used in scenarios where you need efficient traversal in both forward and backward directions, such as implementing undo/redo functionality in text editors, navigation systems, and managing browser history.
  4. What are the benefits of having a Doubly Linked List?

    A Doubly Linked List is a type of linked list where each node has references to both the next and previous nodes. Its advantages include efficient traversal in both directions, easy insertion/deletion at any position, and better memory utilization compared to singly linked lists for certain operations.
  5. What is the difference between Doubly and Circular Linked Lists?

    The main difference between a Doubly Linked List and a Circular Linked List is the structure of their connections. In a Doubly Linked List, each node has references to both the next and previous nodes, whereas, in a Circular Linked List, the last node points back to the first node, forming a loop.
Mukesh Kumar

Mukesh Kumar

Working with upGrad as a Senior Engineering Manager with more than 10+ years of experience in Software Development and Product Management.

Get Free Career Counselling
form image
+91
*
By clicking, I accept theT&Cand
Privacy Policy
image
right-top-arrowleft-top-arrow

upGrad Learner Support

Talk to our experts. We’re available 24/7.

text

Indian Nationals

1800 210 2020

text

Foreign Nationals

+918045604032

Disclaimer

upGrad does not grant credit; credits are granted, accepted or transferred at the sole discretion of the relevant educational institution offering the diploma or degree. We advise you to enquire further regarding the suitability of this program for your academic, professional requirements and job prospects before enr...