23 - JavaScript - Singly LinkedList

23 - JavaScript - Singly LinkedList

A singly linked list is a linear data structure that is made up of nodes. Each node contains a data element and a reference to the next node in the list. The first node in the list is called the head, and the last node is called the tail. If a node's next reference is null, it signifies the end of the list.

In a singly linked list, nodes can only be traversed in one direction, from the head to the tail. This means that it is not possible to access a node in the middle of the list without traversing all the nodes before it.

Singly linked lists are commonly used in computer programming because they are relatively simple to implement and can be used to represent a variety of data structures, such as stacks and queues. They are also useful for implementing dynamic data structures because they allow nodes to be easily added or removed from the list.

Common operations performed on singly linked lists include inserting a node at the beginning, inserting a node at the end, inserting a node at a specific position, deleting a node at a specific position, searching for a node with a specific data element, and printing the entire list. These operations can be implemented using simple traversal algorithms that move through the list one node at a time, updating references as necessary to maintain the integrity of the list.

Visualization Of Singly LinkedList

Here's a basic visualization of a singly linked list:

+-------+    +-------+    +-------+    +-------+
|  Data | -> |  Data | -> |  Data | -> |  Data |
+-------+    +-------+    +-------+    +-------+
|  Next | -> |  Next | -> |  Next | -> |  Next | -> NULL
+-------+    +-------+    +-------+    +-------+
  Head         Node 1       Node 2       Tail

Each box represents a node, which contains a data element and a reference to the next node. The arrow represents the reference, which points from one node to the next. The head of the list is the first node, and the tail of the list is the last node. The tail node's next reference points to NULL, indicating the end of the list.

Syntax Of Singly Linked List

The syntax for a singly linked list implementation in a programming language such as JavaScript is as follows:

// Define the Node class
class Node {
  constructor(data) {
    this.data = data;
    this.next = null;
  }
}

// Define the SinglyLinkedList class
class SinglyLinkedList {
  constructor() {
    this.head = null;
  }

  // Methods for inserting, deleting, searching, and printing nodes would go here
}

In this example, the Node class represents an individual node in the list, with a data property and a next property that references the next node in the list. The SinglyLinkedList class represents the list itself, with a head property that references the first node in the list. The methods for manipulating the list would be defined as member functions of the SinglyLinkedList class.

Code Examples

  1. Insert node at the beginning

    Inserting a node at the beginning of a singly linked list involves creating a new node and updating the head reference to point to the new node. This can be accomplished with the following steps:

    a) Create a new node with the specified data element.

    b) Set the next property of the new node to the current head of the list.

    c) Update the head property of the list to point to the new node.

    Here's an example implementation of inserting a node at the beginning of a singly linked list in JavaScript:

     // Node class for creating individual nodes
     class Node {
       constructor(data, next = null) {
         this.data = data;
         this.next = next;
       }
     }
    
     // Singly linked list class
     class SinglyLinkedList {
       constructor() {
         this.head = null;
         this.size = 1;
       }
    
       // Insert node at the beginning
       insertAtBeginning(data) {
         this.head = new Node(data, this.head);
         this.size++;
       }
    
       // Print the linked list
       print() {
         let current = this.head;
         while (current) {
           console.log(current.data);
           current = current.next;
         }
       }
     }
    

    In this example, the insertAtBeginning method takes a data parameter, which is used to create a new node. The next property of the new node is set to the current head of the list, and the head property of the list is updated to point to the new node. This effectively inserts the new node at the beginning of the list.

    Here's an example usage of the insertAtBeginning method:

     const myList = new SinglyLinkedList();
     myList.insertAtBeginning(5); // list is now: 5 -> NULL
     myList.insertAtBeginning(10); // list is now: 10 -> 5 -> NULL
     myList.insertAtBeginning(15); // list is now: 15 -> 10 -> 5 -> NULL
    

    In this example, we create a new singly linked list called myList and insert three nodes at the beginning of the list using the insertAtBeginning method. The resulting list is 15 -> 10 -> 5 -> NULL.

     myList.print()
    
     15
     10
     5
    
  2. Insert node at the end

    Inserting a node at the end of a singly linked list involves creating a new node and updating the next reference of the last node in the list to point to the new node. This can be accomplished with the following steps:

    a) Create a new node with the specified data element.

    b) Traverse the list until the last node is reached.

    c) Set the next property of the last node to point to the new node.

    Here's an example implementation of inserting a node at the end of a singly linked list in JavaScript:

     // Node class for creating individual nodes
     class Node {
       constructor(data, next = null) {
         this.data = data;
         this.next = next;
       }
     }
    
     // Singly linked list class
     class SinglyLinkedList {
       constructor() {
         this.head = null;
         this.size = 1;
       }
    
       // Insert node at the end
       insertAtEnd(data) {
         const newNode = new Node(data);
         let current;
         if (!this.head) {
           this.head = newNode;
         } else {
           current = this.head;
           while (current.next) {
             current = current.next;
           }
           current.next = newNode;
         }
         this.size++;
       }
    
       // Print the linked list
       print() {
         let current = this.head;
         while (current) {
           console.log(current.data);
           current = current.next;
         }
       }
     }
    

    In this example, the insertAtEnd method takes a data parameter, which is used to create a new node. If the list is empty, the new node is set as the head of the list. Otherwise, the list is traversed until the last node is reached, and the next property of the last node is set to the new node.

    Here's an example usage of the insertAtEnd method:

     const myList = new SinglyLinkedList();
     myList.insertAtEnd(5); // list is now: 5 -> NULL
     myList.insertAtEnd(10); // list is now: 5 -> 10 -> NULL
     myList.insertAtEnd(15); // list is now: 5 -> 10 -> 15 -> NULL
    

    In this example, we create a new singly linked list called myList and insert three nodes at the end of the list using the insertAtEnd method. The resulting list is 5 -> 10 -> 15 -> NULL.

     myList.print()
    
     5
     10
     15
    
  3. Insert node at specific position

    Inserting a node at a specific position in a singly linked list involves creating a new node and updating the next references of the nodes before and after the insertion point to point to the new node. This can be accomplished with the following steps:

    a) Create a new node with the specified data element.

    b) Traverse the list to the node that comes before the insertion point.

    c) Update the next reference of the previous node to point to the new node.

    d) Update the next reference of the new node to point to the node that was originally at the insertion point.

    Here's an example implementation of inserting a node at a specific position in a singly linked list in JavaScript:

     // Node class for creating individual nodes
     class Node {
       constructor(data, next = null) {
         this.data = data;
         this.next = next;
       }
     }
    
     // Singly linked list class
     class SinglyLinkedList {
       constructor() {
         this.head = null;
         this.size = 1;
       }
    
       // Insert node at the end
       insertAtEnd(data) {
         const newNode = new Node(data);
         let current;
         if (!this.head) {
           this.head = newNode;
         } else {
           current = this.head;
           while (current.next) {
             current = current.next;
           }
           current.next = newNode;
         }
         this.size++;
       }
    
       // Insert node at the beginning
       insertAtBeginning(data) {
         this.head = new Node(data, this.head);
         this.size++;
       }
    
       // Insert node at specific position
       insertAtPosition(data, position) {
         if (position < 1 || position > this.size) {
           return null;
         }
         if (position === 1) {
           this.insertAtBeginning(data);
         } else if (position === this.size) {
           this.insertAtEnd(data);
         } else {
           const newNode = new Node(data);
           let current = this.head;
           let previous;
           let count = 1;
           while (count < position) {
             previous = current;
             current = current.next;
             count++;
           }
           newNode.next = current;
           previous.next = newNode;
           this.size++;
         }
       }
    
       // Print the linked list
       print() {
         let current = this.head;
         while (current) {
           console.log(current.data);
           current = current.next;
         }
       }
     }
    

    In this example, the insertAtPosition method takes two parameters: data and position. The data parameter is used to create a new node, and the position parameter specifies the position at which to insert the new node. If the position is 1, the new node is set as the head of the list. Otherwise, the list is traversed to the node before the insertion point, and the next references of the nodes before and after the insertion point are updated to point to the new node.

    Here's an example usage of the insertAtPosition method:

     const myList = new SinglyLinkedList();
     myList.insertAtEnd(5); // list is now: 5 -> NULL
     myList.insertAtEnd(10); // list is now: 5 -> 10 -> NULL
     myList.insertAtPosition(15, 2); // list is now: 5 -> 15 -> 10 -> NULL
    

    In this example, we create a new singly linked list called myList and insert three nodes using the insertAtEnd method. We then insert a new node with a value of 15 at position 2 using the insertAtPosition method. The resulting list is 5 -> 15 -> 10 -> NULL.

     myList.print()
    
     5
     15
     10
    
  4. Delete node at specific position

    Deleting a node at a specific position in a singly linked list involves updating the next references of the nodes before and after the deletion point to bypass the node being deleted. This can be accomplished with the following steps:

    a) Traverse the list to the node that comes before the deletion point.

    b) Update the next reference of the previous node to point to the node after the deletion point.

    c) Update the next reference of the node at the deletion point to null to remove it from the list.

    Here's an example implementation of deleting a node at a specific position in a singly linked list in JavaScript:

     // Node class for creating individual nodes
     class Node {
       constructor(data, next = null) {
         this.data = data;
         this.next = next;
       }
     }
    
     // Singly linked list class
     class SinglyLinkedList {
       constructor() {
         this.head = null;
         this.size = 1;
       }
    
       // Insert node at the end
       insertAtEnd(data) {
         const newNode = new Node(data);
         let current;
         if (!this.head) {
           this.head = newNode;
         } else {
           current = this.head;
           while (current.next) {
             current = current.next;
           }
           current.next = newNode;
         }
         this.size++;
       }
    
       // Delete node at specific position
       deleteAtPosition(position) {
         if (position < 1 || position >= this.size) {
           return null;
         }
         let current = this.head;
         let previous;
         let count = 1;
         if (position === 1) {
           this.head = current.next;
         } else {
           while (count < position) {
             previous = current;
             current = current.next;
             count++;
           }
           previous.next = current.next;
         }
         this.size--;
         return current.data;
       }
    
       // Print the linked list
       print() {
         let current = this.head;
         while (current) {
           console.log(current.data);
           current = current.next;
         }
       }
     }
    

    In this example, the deleteAtPosition method takes one parameter: position, which specifies the position of the node to be deleted. If the position is 1, the next node after the head is set as the new head. Otherwise, the list is traversed to the node before the deletion point, and the next references of the nodes before and after the deletion point are updated to bypass the node being deleted.

    Here's an example usage of the deleteAtPosition method:

     const myList = new SinglyLinkedList();
     myList.insertAtEnd(5); // list is now: 5 -> NULL
     myList.insertAtEnd(10); // list is now: 5 -> 10 -> NULL
     myList.insertAtEnd(15); // list is now: 5 -> 10 -> 15 -> NULL
     myList.deleteAtPosition(2); // list is now: 5 -> 15 -> NULL
    

    In this example, we create a new singly linked list called myList and insert three nodes using the insertAtEnd method. We then delete the node at position 2 using the deleteAtPosition method. The resulting list is 5 -> 15 -> NULL.

     myList.print()
    
     5
     15
    
  5. Search for node with specific data

    Searching for a node with specific data in a singly linked list involves traversing the list and comparing the data in each node with the target data until a match is found. This can be accomplished with the following steps:

    a) Traverse the list, starting at the head node.

    b) Compare the data in each node with the target data.

    c) If a match is found, return the node. If the end of the list is reached without finding a match, return null.

    Here's an example implementation of searching for a node with specific data in a singly linked list in JavaScript:

     // Node class for creating individual nodes
     class Node {
       constructor(data, next = null) {
         this.data = data;
         this.next = next;
       }
     }
    
     // Singly linked list class
     class SinglyLinkedList {
       constructor() {
         this.head = null;
         this.size = 1;
       }
    
       // Insert node at the end
       insertAtEnd(data) {
         const newNode = new Node(data);
         let current;
         if (!this.head) {
           this.head = newNode;
         } else {
           current = this.head;
           while (current.next) {
             current = current.next;
           }
           current.next = newNode;
         }
         this.size++;
       }
    
       // Search for node with specific data
       search(data) {
         let current = this.head;
         while (current) {
           if (current.data === data) {
             return current;
           }
           current = current.next;
         }
         return null;
       }
    
       // Print the linked list
       print() {
         let current = this.head;
         while (current) {
           console.log(current.data);
           current = current.next;
         }
       }
     }
    

    In this example, the search method takes one parameter: data, which is the data to search for. The list is traversed, and the data property of each node is compared to the target data. If a match is found, the node is returned. If the end of the list is reached without finding a match, null is returned.

    Here's an example usage of the search method:

     const myList = new SinglyLinkedList();
     myList.insertAtEnd(5); // list is now: 5 -> NULL
     myList.insertAtEnd(10); // list is now: 5 -> 10 -> NULL
     myList.insertAtEnd(15); // list is now: 5 -> 10 -> 15 -> NULL
     const node = myList.search(10); // returns the node with data 10
    

    In this example, we create a new singly linked list called myList and insert three nodes using the insertAtEnd method. We then search for the node with data 10 using the search method, which returns the node with data 10.

     console.log(node);
    
     Node { data: 10, next: Node { data: 15, next: null } }
    

Summarizing Up

A singly linked list is a linear data structure where each node points to the next node in the sequence. It consists of nodes that contain a data element and a reference to the next node in the list. The first node is called the head and the last node is called the tail, which points to null. Singly linked lists can be used to implement dynamic data structures such as stacks, queues, and hash tables. They are useful for handling large amounts of data efficiently because nodes can be easily inserted or removed without moving the other elements in the list.

Did you find this article valuable?

Support Bosonique ITEdTech by becoming a sponsor. Any amount is appreciated!