Close Menu
ExamsmetaExamsmeta
  • Science
    • Physics
    • Chemistry
    • Mathematics
    • Biology
    • Geology
    • Computer Science
    • Environmental Science
    • Medical Science
  • Commerce
    • Accountancy
    • Business Studies
    • Business Administration
    • Bank Management
    • Economics
    • Finance
    • Management
    • Marketing
  • Humanities
    • History
    • Economics
    • Geography
    • Social Science
    • Sociology
    • Psychology
    • Philosophy
    • Political Science
  • Computer Science
    • Data Structures
    • Algorithms
    • Python
    • Machine Learning
    • Data Science
    • Data Analytics
    • System Design
    • Programming
    • Database Management
    • Web Development
    • DevOps
    • Linux Tutorials
  • Higher Studies
    • Aviation
    • Astronomy
    • Aeronautics
    • Agriculture
    • Architecture
    • Anthropology
    • Biotechnology
    • Energy Studies
    • Earth Science
    • Design Studies
    • Healthcare Studies
    • Engineering Studies
    • Statistical Studies
    • Computer Networking
    • Computer Applications
    • Wireless Communication
    • International Relations
    • Public Administration
    • Human Resources
    • Communication
  • Exams
    • Exams In India
    • Exams In America
    • Exams In Canada
    • Exams In The UK
    • Exams In Australia
    • Exams In New Zealand
    • Exam Results
  • More Menus
    • Articles
    • Biographies
    • General Knowledge
    • Education
    • Cybersecurity
    • Internet Working
    • Information Technology
    • Google Workspace
    • Microsoft Office
  • Website
    • About Examsmeta
    • Cookies Policy
    • Privacy Policy
    • Terms of Use
    • Contact Us
    • Email
Facebook Instagram X (Twitter) Pinterest YouTube Reddit
  • About
  • Cookies
  • Privacy
  • Terms
  • Contact
  • Email
Facebook Instagram X (Twitter) Pinterest YouTube LinkedIn
ExamsmetaExamsmeta
  • Science
    • Physics
    • Chemistry
    • Mathematics
    • Biology
    • Geology
    • Computer Science
    • Environmental Science
    • Medical Science
  • Commerce
    • Accountancy
    • Business Studies
    • Business Administration
    • Bank Management
    • Economics
    • Finance
    • Management
    • Marketing
  • Humanities
    • History
    • Economics
    • Geography
    • Social Science
    • Sociology
    • Psychology
    • Philosophy
    • Political Science
  • Computer Science
    • Data Structures
    • Algorithms
    • Python
    • Machine Learning
    • Data Science
    • Data Analytics
    • System Design
    • Programming
    • Database Management
    • Web Development
    • DevOps
    • Linux Tutorials
  • Higher Studies
    • Aviation
    • Astronomy
    • Aeronautics
    • Agriculture
    • Architecture
    • Anthropology
    • Biotechnology
    • Energy Studies
    • Earth Science
    • Design Studies
    • Healthcare Studies
    • Engineering Studies
    • Statistical Studies
    • Computer Networking
    • Computer Applications
    • Wireless Communication
    • International Relations
    • Public Administration
    • Human Resources
    • Communication
  • Exams
    • Exams In India
    • Exams In America
    • Exams In Canada
    • Exams In The UK
    • Exams In Australia
    • Exams In New Zealand
    • Exam Results
  • More Menus
    • Articles
    • Biographies
    • General Knowledge
    • Education
    • Cybersecurity
    • Internet Working
    • Information Technology
    • Google Workspace
    • Microsoft Office
  • Website
    • About Examsmeta
    • Cookies Policy
    • Privacy Policy
    • Terms of Use
    • Contact Us
    • Email
ExamsmetaExamsmeta
Data Structures

Understanding Singly Linked Lists: A Detailed Exploration

By Examsmeta
Share
Facebook Twitter Copy Link

Singly Linked Lists, also referred to as one-way chains, are a foundational concept in data structures and programming. They offer a flexible and efficient way to organize and manipulate data, especially when the number of elements may vary during runtime. In this comprehensive post, we will delve deeply into the definition, structure, and operations performed on Singly Linked Lists.

Table of Contents

  • What is a Singly Linked List?
  • Key Features of Singly Linked Lists
  • Time Complexity
  • Operations on Singly Linked Lists
  • Advantages of Singly Linked Lists
  • Disadvantages of Singly Linked Lists
  • Linked List in C Program – Menu Driven Program
  • Example of Implementation of Singly Linked List in Multiple Programming Languages
  • Read More Articles
  • Frequently Asked Questions (FAQs) about Singly Linked Lists

What is a Singly Linked List?

A singly linked list is a dynamic data structure that consists of a sequence of elements called nodes, arranged in a linear order. Each node in this list has two components:

  1. Data Part: Stores the actual information or value.
  2. Link Part: Contains the memory address or reference of the next node in the sequence.
Singly Linked list

One of the defining characteristics of singly linked lists is their unidirectional nature—nodes can only be traversed in one direction. The link part of the last node always points to null, indicating the end of the list.

For example, consider storing the marks of a student in three subjects (25, 35, and 90). Each subject’s marks can be represented as the data part of a node, while the link part establishes the connection to the next node, forming a chain-like structure.

Singly Linked Lists Example

Key Features of Singly Linked Lists

  1. Dynamic Memory Allocation: Unlike arrays, singly linked lists do not require pre-allocation of memory. Nodes are created dynamically, depending on the program’s requirements.
  2. Efficient Insertion/Deletion: Adding or removing elements does not require shifting other elements, as in arrays, making these operations more efficient.
  3. Unidirectional Traversal: Nodes can only be traversed from the head (starting node) to the tail (last node).

Time Complexity

Here’s a detailed table outlining the time complexity of various operations performed on a singly linked list:

OperationBest CaseWorst CaseAverage CaseExplanation
Access (Indexing)N/AO(n)O(n)A singly linked list does not support direct access, requiring traversal from the head.
SearchO(1)O(n)O(n)Best case occurs when the target element is at the head; otherwise, traversal is required.
Insertion at BeginningO(1)O(1)O(1)Only a few pointer adjustments are needed.
Insertion at EndO(1)*O(n)O(n)If a tail pointer exists, it’s O(1); otherwise, traversal is required to find the last node.
Insertion After NodeO(1)O(n)O(n)Finding the specified node takes O(n), but the actual insertion is O(1).
Deletion at BeginningO(1)O(1)O(1)Only the head pointer needs to be updated.
Deletion at EndO(1)*O(n)O(n)With a tail pointer, it’s O(1); otherwise, traversal to the second-to-last node is required.
Deletion After NodeO(1)O(n)O(n)Finding the specified node is O(n), but removing the next node is O(1).
TraversalO(n)O(n)O(n)Visiting each node once requires a complete traversal of the list.

Key Notes:

  1. O(1) Operations: Insertions and deletions at the beginning are highly efficient because they require no traversal.
  2. Tail Pointer Optimization: If a tail pointer is maintained, insertion or deletion at the end can be reduced to O(1). However, this adds complexity to the implementation.
  3. Searching and Access: Due to the sequential nature of singly linked lists, these operations generally require a traversal of the list, leading to O(n) complexity.

This table emphasizes why singly linked lists are efficient for dynamic insertion and deletion but less optimal for random access or searching compared to arrays or hash tables.

Operations on Singly Linked Lists

Singly linked lists support a variety of operations that allow for effective data manipulation. Below, we explore these operations in detail:

Node Creation

Creating a node is the foundation of building a linked list. The typical structure of a node in C programming language is defined as:

struct node {
    int data;
    struct node *next;
};


Here:

  • data stores the value.
  • next is a pointer that holds the address of the next node.

A node can be dynamically allocated using the malloc function:

struct node *ptr;
ptr = (struct node *)malloc(sizeof(struct node *));

Insertion Operations

Insertion into a singly linked list can be categorized based on where the new node is added.

1. Insertion at the Beginning

This operation involves adding a node at the very front of the list. The steps include:

  1. Creating a new node.
  2. Pointing the new node’s next pointer to the current head.
  3. Updating the head to the new node.

This is an efficient operation as it requires minimal adjustments.

2. Insertion at the End

Here, a new node is added to the end of the list. The process varies depending on whether the list is empty or contains elements:

  1. If the list is empty, the new node becomes the head.
  2. Otherwise, traverse to the last node and update its next pointer to the new node.

3. Insertion After a Specific Node

To insert a node after a specific node:

  1. Traverse the list to locate the target node.
  2. Update the next pointer of the new node to the next pointer of the target node.
  3. Adjust the target node’s next pointer to point to the new node.

Deletion Operations

1. Deletion at the Beginning

To remove the first node:

  1. Update the head pointer to the second node.
  2. Free the memory of the removed node.

This is a straightforward operation requiring minimal adjustments.

2. Deletion at the End

Deleting the last node involves:

  1. Traversing the list to find the second-to-last node.
  2. Updating its next pointer to null.
  3. Freeing the memory of the removed node.

3. Deletion After a Specific Node

This operation involves:

  1. Traversing the list to locate the specified node.
  2. Updating its next pointer to skip the target node.
  3. Freeing the memory of the skipped node.

Traversing the Singly Linked List

Traversal refers to visiting each node in the list at least once, often to perform operations like printing data values. The process is simple:

  1. Start at the head.
  2. Follow the links using the next pointer until the last node (null) is reached.

Traversal is essential for performing other operations such as insertion, deletion, or searching.

Searching in Singly Linked Lists

In searching, each node’s data part is compared with the target value. If a match is found, the position of the node is returned. If no match exists, null is returned. This operation requires traversing the entire list in the worst case.

Advantages of Singly Linked Lists

  1. Dynamic Size: The number of nodes can grow or shrink based on the program’s requirements.
  2. Efficient Memory Utilization: Nodes are allocated memory as needed, avoiding wastage.
  3. Fast Insertions/Deletions: Unlike arrays, no need to shift elements during insertion or deletion.

Disadvantages of Singly Linked Lists

  1. Sequential Access: Traversal is unidirectional, making reverse operations challenging.
  2. Higher Memory Overhead: The link part of each node requires additional memory.
  3. No Direct Access: To access a specific node, traversal from the head is necessary.

Linked List in C Program – Menu Driven Program

#include<stdio.h>
#include<stdlib.h>

// Define the structure for a node
struct node {
    int data;
    struct node *next;
};

struct node *head = NULL; // Initialize head pointer to NULL

// Function prototypes
void beginsert();
void lastinsert();
void randominsert();
void begin_delete();
void last_delete();
void random_delete();
void display();
void search();

void main() {
    int choice = 0;  
    while(choice != 9) {
        printf("\n\n********* Main Menu *********\n");
        printf("1. Insert at the beginning\n");
        printf("2. Insert at the end\n");
        printf("3. Insert at a specific position\n");
        printf("4. Delete from the beginning\n");
        printf("5. Delete from the end\n");
        printf("6. Delete from a specific position\n");
        printf("7. Search for an element\n");
        printf("8. Display the list\n");
        printf("9. Exit\n");
        printf("Enter your choice: ");
        scanf("%d", &choice);

        switch(choice) {
            case 1:
                beginsert();
                break;
            case 2:
                lastinsert();
                break;
            case 3:
                randominsert();
                break;
            case 4:
                begin_delete();
                break;
            case 5:
                last_delete();
                break;
            case 6:
                random_delete();
                break;
            case 7:
                search();
                break;
            case 8:
                display();
                break;
            case 9:
                printf("Exiting...\n");
                break;
            default:
                printf("Please enter a valid choice.\n");
        }
    }
}

// Function to insert a node at the beginning
void beginsert() {
    struct node *ptr = (struct node *)malloc(sizeof(struct node));
    if(ptr == NULL) {
        printf("Memory overflow.\n");
        return;
    }
    printf("Enter the value to insert: ");
    int item;
    scanf("%d", &item);
    ptr->data = item;
    ptr->next = head;
    head = ptr;
    printf("Node inserted at the beginning.\n");
}

// Function to insert a node at the end
void lastinsert() {
    struct node *ptr = (struct node *)malloc(sizeof(struct node));
    if(ptr == NULL) {
        printf("Memory overflow.\n");
        return;
    }
    printf("Enter the value to insert: ");
    int item;
    scanf("%d", &item);
    ptr->data = item;
    ptr->next = NULL;
    if(head == NULL) {
        head = ptr;
    } else {
        struct node *temp = head;
        while(temp->next != NULL) {
            temp = temp->next;
        }
        temp->next = ptr;
    }
    printf("Node inserted at the end.\n");
}

// Function to insert a node at a specific position
void randominsert() {
    struct node *ptr = (struct node *)malloc(sizeof(struct node));
    if(ptr == NULL) {
        printf("Memory overflow.\n");
        return;
    }
    printf("Enter the value to insert: ");
    int item;
    scanf("%d", &item);
    ptr->data = item;

    printf("Enter the position after which to insert: ");
    int loc;
    scanf("%d", &loc);
    struct node *temp = head;
    for(int i = 1; i < loc; i++) {
        if(temp == NULL) {
            printf("Invalid position.\n");
            return;
        }
        temp = temp->next;
    }
    ptr->next = temp->next;
    temp->next = ptr;
    printf("Node inserted at position %d.\n", loc + 1);
}

// Function to delete the first node
void begin_delete() {
    if(head == NULL) {
        printf("List is empty.\n");
        return;
    }
    struct node *ptr = head;
    head = head->next;
    free(ptr);
    printf("Node deleted from the beginning.\n");
}

// Function to delete the last node
void last_delete() {
    if(head == NULL) {
        printf("List is empty.\n");
        return;
    }
    if(head->next == NULL) {
        free(head);
        head = NULL;
        printf("Only node deleted.\n");
        return;
    }
    struct node *temp = head;
    while(temp->next->next != NULL) {
        temp = temp->next;
    }
    free(temp->next);
    temp->next = NULL;
    printf("Node deleted from the end.\n");
}

// Function to delete a node at a specific position
void random_delete() {
    if(head == NULL) {
        printf("List is empty.\n");
        return;
    }
    printf("Enter the position after which to delete: ");
    int loc;
    scanf("%d", &loc);
    struct node *temp = head, *prev = NULL;
    for(int i = 0; i < loc; i++) {
        prev = temp;
        temp = temp->next;
        if(temp == NULL) {
            printf("Invalid position.\n");
            return;
        }
    }
    prev->next = temp->next;
    free(temp);
    printf("Node deleted at position %d.\n", loc + 1);
}

// Function to search for an element in the list
void search() {
    if(head == NULL) {
        printf("List is empty.\n");
        return;
    }
    printf("Enter the element to search for: ");
    int item;
    scanf("%d", &item);
    struct node *temp = head;
    int pos = 1;
    while(temp != NULL) {
        if(temp->data == item) {
            printf("Element found at position %d.\n", pos);
            return;
        }
        temp = temp->next;
        pos++;
    }
    printf("Element not found.\n");
}

// Function to display the list
void display() {
    if(head == NULL) {
        printf("List is empty.\n");
        return;
    }
    struct node *temp = head;
    printf("List elements: ");
    while(temp != NULL) {
        printf("%d -> ", temp->data);
        temp = temp->next;
    }
    printf("NULL\n");
}

Key Points and Steps in the Code:

  1. Node Structure:
    Defines a node with two fields: data (to store the value) and next (to store the address of the next node).
  2. Head Pointer Initialization:
    The head pointer is initialized to NULL to represent an empty list.
  3. Insertion Functions:
    • beginsert: Adds a node at the beginning of the list.
    • lastinsert: Adds a node at the end of the list.
    • randominsert: Adds a node at a specified position.
  4. Deletion Functions:
    • begin_delete: Removes the first node.
    • last_delete: Removes the last node.
    • random_delete: Removes a node at a specified position.
  5. Search Function:
    Iterates through the list to find an element and prints its position.
  6. Display Function:
    Prints all the elements in the list in order.

Sample Output:

********* Main Menu *********
1. Insert at the beginning
2. Insert at the end
3. Insert at a specific position
4. Delete from the beginning
5. Delete from the end
6. Delete from a specific position
7. Search for an element
8. Display the list
9. Exit
Enter your choice: 1
Enter the value to insert: 10
Node inserted at the beginning.

Enter your choice: 8
List elements: 10 -> NULL

Singly linked lists are a simple yet powerful tool in programming, forming the basis for more complex structures like doubly linked lists, circular linked lists, and even trees. Mastering their implementation and operations is crucial for anyone delving into data structures and algorithms. Whether you’re storing a student’s marks or designing a compiler, the flexibility and efficiency of singly linked lists make them indispensable in software development.

Example of Implementation of Singly Linked List in Multiple Programming Languages

A Singly Linked List is a linear data structure consisting of nodes where each node has two parts:

  1. Data: Stores the actual value of the node.
  2. Next Pointer: Points to the next node in the list, or NULL if it’s the last node.

The common operations on a singly linked list include:

  • Insertion at the beginning, at the end, or at a specific position.
  • Deletion from the beginning, the end, or a specific position.
  • Traversal to print all elements of the list.
  • Search to find a specific element.
  • C
  • C ++
  • C#
  • Python

Code:

#include<stdio.h>
#include<stdlib.h>

// Define the structure for a node
struct node {
    int data;
    struct node *next;
};

// Function prototypes
void insert_at_beginning();
void insert_at_end();
void display();
void search();

struct node *head = NULL; // Initialize head pointer to NULL

int main() {
    int choice = 0;
    while (choice != 5) {
        printf("\nMenu:\n");
        printf("1. Insert at the beginning\n");
        printf("2. Insert at the end\n");
        printf("3. Display the list\n");
        printf("4. Search for an element\n");
        printf("5. Exit\n");
        printf("Enter your choice: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                insert_at_beginning();
                break;
            case 2:
                insert_at_end();
                break;
            case 3:
                display();
                break;
            case 4:
                search();
                break;
            case 5:
                printf("Exiting...\n");
                break;
            default:
                printf("Invalid choice\n");
        }
    }
    return 0;
}

// Insert at the beginning
void insert_at_beginning() {
    struct node *new_node = (struct node*) malloc(sizeof(struct node));
    printf("Enter the value to insert: ");
    scanf("%d", &new_node->data);
    new_node->next = head;
    head = new_node;
    printf("Node inserted at the beginning.\n");
}

// Insert at the end
void insert_at_end() {
    struct node *new_node = (struct node*) malloc(sizeof(struct node));
    struct node *temp = head;
    printf("Enter the value to insert: ");
    scanf("%d", &new_node->data);
    new_node->next = NULL;

    if (head == NULL) {
        head = new_node;
        return;
    }

    while (temp->next != NULL) {
        temp = temp->next;
    }

    temp->next = new_node;
    printf("Node inserted at the end.\n");
}

// Display the list
void display() {
    if (head == NULL) {
        printf("The list is empty.\n");
        return;
    }

    struct node *temp = head;
    printf("List: ");
    while (temp != NULL) {
        printf("%d -> ", temp->data);
        temp = temp->next;
    }
    printf("NULL\n");
}

// Search for an element
void search() {
    int value;
    printf("Enter value to search: ");
    scanf("%d", &value);
    struct node *temp = head;
    int found = 0;
    while (temp != NULL) {
        if (temp->data == value) {
            printf("Element %d found.\n", value);
            found = 1;
            break;
        }
        temp = temp->next;
    }
    if (!found) {
        printf("Element %d not found.\n", value);
    }
}

Explanation

  • We define a struct node containing an integer data and a pointer next pointing to the next node.
  • head is a global pointer that points to the first node of the list.
  • Insertion: We insert nodes at the beginning or end, adjusting the next pointers.
  • Display: The list is traversed, and each node’s data is printed.
  • Search: We traverse the list to find a node with the specified data.

Code:

#include<iostream>
using namespace std;

struct Node {
    int data;
    Node* next;
};

Node* head = NULL;

void insert_at_beginning();
void insert_at_end();
void display();
void search();

int main() {
    int choice = 0;
    while (choice != 5) {
        cout << "\nMenu:\n";
        cout << "1. Insert at the beginning\n";
        cout << "2. Insert at the end\n";
        cout << "3. Display the list\n";
        cout << "4. Search for an element\n";
        cout << "5. Exit\n";
        cout << "Enter your choice: ";
        cin >> choice;

        switch (choice) {
            case 1:
                insert_at_beginning();
                break;
            case 2:
                insert_at_end();
                break;
            case 3:
                display();
                break;
            case 4:
                search();
                break;
            case 5:
                cout << "Exiting...\n";
                break;
            default:
                cout << "Invalid choice\n";
        }
    }
    return 0;
}

void insert_at_beginning() {
    Node* new_node = new Node;
    cout << "Enter the value to insert: ";
    cin >> new_node->data;
    new_node->next = head;
    head = new_node;
    cout << "Node inserted at the beginning.\n";
}

void insert_at_end() {
    Node* new_node = new Node;
    cout << "Enter the value to insert: ";
    cin >> new_node->data;
    new_node->next = NULL;

    if (head == NULL) {
        head = new_node;
        return;
    }

    Node* temp = head;
    while (temp->next != NULL) {
        temp = temp->next;
    }

    temp->next = new_node;
    cout << "Node inserted at the end.\n";
}

void display() {
    if (head == NULL) {
        cout << "The list is empty.\n";
        return;
    }

    Node* temp = head;
    cout << "List: ";
    while (temp != NULL) {
        cout << temp->data << " -> ";
        temp = temp->next;
    }
    cout << "NULL\n";
}

void search() {
    int value;
    cout << "Enter value to search: ";
    cin >> value;
    Node* temp = head;
    bool found = false;
    while (temp != NULL) {
        if (temp->data == value) {
            cout << "Element " << value << " found.\n";
            found = true;
            break;
        }
        temp = temp->next;
    }
    if (!found) {
        cout << "Element " << value << " not found.\n";
    }
}

Explanation

  • In C++, we use the new keyword for dynamic memory allocation.
  • The logic for insertion, display, and search is similar to the C program, with syntax differences like cin and cout.

Code:

using System;

class SinglyLinkedList {
    class Node {
        public int data;
        public Node next;
        public Node(int data) {
            this.data = data;
            this.next = null;
        }
    }

    private Node head = null;

    public void InsertAtBeginning() {
        Console.Write("Enter value to insert: ");
        int value = int.Parse(Console.ReadLine());
        Node newNode = new Node(value);
        newNode.next = head;
        head = newNode;
        Console.WriteLine("Node inserted at the beginning.");
    }

    public void InsertAtEnd() {
        Console.Write("Enter value to insert: ");
        int value = int.Parse(Console.ReadLine());
        Node newNode = new Node(value);
        newNode.next = null;

        if (head == null) {
            head = newNode;
            return;
        }

        Node temp = head;
        while (temp.next != null)

 {
            temp = temp.next;
        }

        temp.next = newNode;
        Console.WriteLine("Node inserted at the end.");
    }

    public void Display() {
        if (head == null) {
            Console.WriteLine("The list is empty.");
            return;
        }

        Node temp = head;
        Console.Write("List: ");
        while (temp != null) {
            Console.Write(temp.data + " -> ");
            temp = temp.next;
        }
        Console.WriteLine("NULL");
    }

    public void Search() {
        Console.Write("Enter value to search: ");
        int value = int.Parse(Console.ReadLine());
        Node temp = head;
        bool found = false;
        while (temp != null) {
            if (temp.data == value) {
                Console.WriteLine($"Element {value} found.");
                found = true;
                break;
            }
            temp = temp.next;
        }
        if (!found) {
            Console.WriteLine($"Element {value} not found.");
        }
    }

    public static void Main(string[] args) {
        SinglyLinkedList sll = new SinglyLinkedList();
        int choice = 0;
        while (choice != 5) {
            Console.WriteLine("\nMenu:");
            Console.WriteLine("1. Insert at the beginning");
            Console.WriteLine("2. Insert at the end");
            Console.WriteLine("3. Display the list");
            Console.WriteLine("4. Search for an element");
            Console.WriteLine("5. Exit");
            Console.Write("Enter your choice: ");
            choice = int.Parse(Console.ReadLine());

            switch (choice) {
                case 1: sll.InsertAtBeginning(); break;
                case 2: sll.InsertAtEnd(); break;
                case 3: sll.Display(); break;
                case 4: sll.Search(); break;
                case 5: Console.WriteLine("Exiting..."); break;
                default: Console.WriteLine("Invalid choice!"); break;
            }
        }
    }
}

Explanation:

  • The Node class is nested inside the SinglyLinkedList class.
  • Memory management is automatic in C# using garbage collection.
  • Insertion, display, and search logic are similar to the previous examples.

Code:

class SinglyLinkedList:
    class Node:
        def __init__(self, data):
            self.data = data
            self.next = None

    def __init__(self):
        self.head = None

    def insert_at_beginning(self):
        value = int(input("Enter value to insert: "))
        new_node = self.Node(value)
        new_node.next = self.head
        self.head = new_node
        print("Node inserted at the beginning.")

    def insert_at_end(self):
        value = int(input("Enter value to insert: "))
        new_node = self.Node(value)
        if self.head is None:
            self.head = new_node
            return

        temp = self.head
        while temp.next:
            temp = temp.next

        temp.next = new_node
        print("Node inserted at the end.")

    def display(self):
        if self.head is None:
            print("The list is empty.")
            return

        temp = self.head
        print("List: ", end="")
        while temp:
            print(temp.data, end=" -> ")
            temp = temp.next
        print("NULL")

    def search(self):
        value = int(input("Enter value to search: "))
        temp = self.head
        while temp:
            if temp.data == value:
                print(f"Element {value} found.")
                return
            temp = temp.next
        print(f"Element {value} not found.")

if __name__ == "__main__":
    sll = SinglyLinkedList()
    while True:
        print("\nMenu:")
        print("1. Insert at the beginning")
        print("2. Insert at the end")
        print("3. Display the list")
        print("4. Search for an element")
        print("5. Exit")
        choice = int(input("Enter your choice: "))

        if choice == 1:
            sll.insert_at_beginning()
        elif choice == 2:
            sll.insert_at_end()
        elif choice == 3:
            sll.display()
        elif choice == 4:
            sll.search()
        elif choice == 5:
            break
        else:
            print("Invalid choice!")

Explanation:

  • Python uses classes to define the linked list and nodes.
  • We insert elements at the beginning or the end and use simple traversal to display and search.
  • Memory management is automatic (garbage collection).

Output:

Menu:
1. Insert at the beginning
2. Insert at the end
3. Display the list
4. Search for an element
5. Exit
Enter your choice: 1
Enter the value to insert: 10
Node inserted at the beginning.

Menu:
1. Insert at the beginning
2. Insert at the end
3. Display the list
4. Search for an element
5. Exit
Enter your choice: 2
Enter the value to insert: 20
Node inserted at the end.

List: 10 -> 20 -> NULL

Theoretical Explanation

  • A Singly Linked List consists of nodes where each node contains two fields: data and a pointer next that points to the next node.
  • The head pointer keeps track of the start of the list.
  • Insertion involves creating a new node and adjusting pointers so that the new node is linked properly (either at the beginning or end).
  • Traversal is done by starting at the head and moving through the nodes using their next pointers until reaching NULL.
  • Search involves checking each node’s data to see if it matches the desired value.

The code provided in C, C++, C#, and Python demonstrates these fundamental operations, adjusting for the syntax and memory management practices of each language.

Read More Articles

  • Data Structure (DS) Array:
    1. Why the Analysis of Algorithms is Important?
    2. Worst, Average, and Best Case Analysis of Algorithms: A Comprehensive Guide
    3. Understanding Pointers in C Programming: A Comprehensive Guide
    4. Understanding Arrays in Data Structures: A Comprehensive Exploration
    5. Memory Allocation of an Array: An In-Depth Comprehensive Exploration
    6. Understanding Basic Operations in Arrays: A Comprehensive Guide
    7. Understanding 2D Arrays in Programming: A Comprehensive Guide
    8. Mapping a 2D Array to a 1D Array: A Comprehensive Exploration
  • Data Structure Linked List:
    1. Understanding Linked Lists in Data Structures: A Comprehensive Exploration
    2. Types of Linked List: Detailed Exploration, Representations, and Implementations
    3. Understanding Singly Linked Lists: A Detailed Exploration
    4. Understanding Doubly Linked List: A Comprehensive Guide
    5. Operations of Doubly Linked List with Implementation: A Detailed Exploration
    6. Insertion in Doubly Linked List with Implementation: A Detailed Exploration
    7. Inserting a Node at the beginning of a Doubly Linked List: A Detailed Exploration
    8. Inserting a Node After a Given Node in a Doubly Linked List: A Detailed Exploration
    9. Inserting a Node Before a Given Node in a Doubly Linked List: A Detailed Exploration
    10. Inserting a Node at a Specific Position in a Doubly Linked List: A Detailed Exploration
    11. Inserting a New Node at the End of a Doubly Linked List: A Detailed Exploration
    12. Deletion in a Doubly Linked List with Implementation: A Comprehensive Guide
    13. Deletion at the Beginning in a Doubly Linked List: A Detailed Exploration
    14. Deletion after a given node in Doubly Linked List: A Comprehensive Guide
    15. Deleting a Node Before a Given Node in a Doubly Linked List: A Detailed Exploration
    16. Deletion at a Specific Position in a Doubly Linked List: A Detailed Exploration
    17. Deletion at the End in Doubly Linked List: A Comprehensive Exploration
    18. Introduction to Circular Linked Lists: A Comprehensive Guide
    19. Understanding Circular Singly Linked Lists: A Comprehensive Guide
    20. Circular Doubly Linked List: A Comprehensive Guide
    21. Insertion in Circular Singly Linked List: A Comprehensive Guide
    22. Insertion in an Empty Circular Linked List: A Detailed Exploration
    23. Insertion at the Beginning in Circular Linked List: A Detailed Exploration
    24. Insertion at the End of a Circular Linked List: A Comprehensive Guide
    25. Insertion at a Specific Position in a Circular Linked List: A Detailed Exploration
    26. Deletion from a Circular Linked List: A Comprehensive Guide
    27. Deletion from the Beginning of a Circular Linked List: A Detailed Exploration
    28. Deletion at Specific Position in Circular Linked List: A Detailed Exploration
    29. Deletion at the End of a Circular Linked List: A Comprehensive Guide
    30. Searching in a Circular Linked List: A Comprehensive Exploration

Frequently Asked Questions (FAQs) about Singly Linked Lists

What is a Singly Linked List?

A singly linked list is a linear data structure where each element (node) contains two parts: a data part that stores the value and a next pointer that holds the address of the next node in the list. The list is unidirectional, meaning that nodes can only be traversed in one direction, from the head (start) to the tail (end).

How does a Singly Linked List differ from an array?

A singly linked list differs from an array in several ways:

  • Dynamic size: Linked lists can grow or shrink in size dynamically, while arrays have a fixed size once allocated.
  • Efficient insertions and deletions: In a linked list, adding or removing elements is faster because elements don’t need to be shifted (unlike arrays).
  • Memory allocation: Linked lists allocate memory only as needed for each node, while arrays pre-allocate a fixed amount of memory.
  • Access time: In arrays, you can access any element in constant time by its index, but in linked lists, you must traverse the list sequentially.

What are the different operations that can be performed on a Singly Linked List?

The primary operations on a singly linked list are:

  • Insertion: Add nodes at the beginning, end, or after a specific node.
  • Deletion: Remove nodes from the beginning, end, or a specific node.
  • Traversal: Visit and print the nodes of the list.
  • Search: Find a node by its value.
  • Update: Modify the value of a specific node.

What are the types of insertion operations in a Singly Linked List?

Insertion operations in a singly linked list include:

  1. Insertion at the beginning: A new node is added at the front, and the head pointer is updated.
  2. Insertion at the end: A new node is added after the last node. If the list is empty, the new node becomes the head.
  3. Insertion after a specific node: A node is inserted after a specified node in the list.

How is a node created in a Singly Linked List?

In a singly linked list, a node is typically created with two components:

  1. Data part: Stores the value of the node.
  2. Next pointer: Points to the next node in the list (or null if it’s the last node).

In C, a node is created dynamically using malloc:

struct node* newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = value;
newNode->next = NULL;

What is the time complexity for insertion at the beginning and at the end of a Singly Linked List?

  • Insertion at the beginning: This operation has a time complexity of O(1), as you only need to adjust the head pointer and the next pointer of the new node.
  • Insertion at the end: This operation has a time complexity of O(n), where n is the number of nodes in the list. This is because you need to traverse the entire list to find the last node before inserting the new node.

How do you delete a node from a Singly Linked List?

There are three types of deletion operations:

  1. Deletion at the beginning: Update the head pointer to the second node and free the memory of the first node.
  2. Deletion at the end: Traverse the list to find the second-to-last node, update its next pointer to null, and free the last node’s memory.
  3. Deletion after a specific node: Traverse the list to locate the node to be deleted, update its next pointer to skip the target node, and free the memory of the deleted node.

What is the time complexity of searching in a Singly Linked List?

Searching for an element in a singly linked list involves traversing the list and comparing each node’s data to the target value. In the worst case, you may need to traverse the entire list. Therefore, the time complexity is O(n), where n is the number of nodes in the list.

Can you traverse a Singly Linked List in reverse?

No, a singly linked list cannot be traversed in reverse because each node only has a reference to the next node, not the previous one. This makes it impossible to move backward. To traverse in reverse, you would need a doubly linked list or an auxiliary stack to store the nodes during traversal and then process them in reverse order.

What are the advantages and disadvantages of using a Singly Linked List?

Advantages:

  • Dynamic size: The list grows or shrinks as needed, without pre-allocating memory.
  • Efficient insertions and deletions: No need to shift elements when adding or removing nodes.
  • Memory efficiency: Memory is allocated only when needed for each node.

Disadvantages:

  • Sequential access: Nodes can only be accessed sequentially, making random access slower.
  • Higher memory overhead: Each node requires extra memory for the next pointer, in addition to the data.
  • No backward traversal: Unlike doubly linked lists, you cannot traverse the list in reverse without extra data structures.
Computer Science Higher Studies
Share. Facebook Twitter Copy Link
Examsmeta Logo
Examsmeta
  • Website
  • Facebook
  • X (Twitter)
  • Pinterest
  • Instagram
  • Tumblr
  • LinkedIn

Examsmeta serves as a comprehensive hub for educational resources across diverse disciplines. Designed to deliver high-quality, topic-wise notes and articles, it caters to students, educators, researchers, and lifelong learners. The goal is to make learning accessible, engaging, and effective for all. With a focus on providing detailed, accurate, and up-to-date content, Examsmeta fosters a passion for learning and supports both academic and professional growth. Whether it's exam preparation, research, or knowledge expansion, this platform offers guidance every step of the way.

Type above and press Enter to search. Press Esc to cancel.