Linked List in Javascript (Data Structures)

Linked List in JavaScript (Data Structures)

Table of contents

No heading

No headings in the article.

A singly linked list is a type of linked list that is unidirectional, that is, it can be traversed in only one direction from the head to the last node (tail). Every node contains some data and a pointer to the next node of the same data type. The node contains a pointer to the next node means that the node stores the address of the next node in the sequence.

Todos:

  1. Push and Pop

  2. Unshift and Shift

  3. Get and Set

  4. Insert and Remove

Creating a node: It contains a value and a pointer.

class Node {
    constructor(val) {
        this.val = val;
        this.next = null;
    }
}

Linked List:

class SinglyLinkedList {
    constructor() {
        this.head = null;
        this.tail = null;
        this.length = 0;
    }

    // methods ....
}

Push: adding a node at the end of the linked list

  1. The function should accept a value.

  2. Create a new node using the value passed to the function.

  3. If there is no head property on the list, set the head and tail to be the newly created node.

  4. Otherwise set the next property on the tail to the new node and set the tail property on the list to be the newly created node.

  5. Increment the length by one.

  6. Return the linked list.

     push(val) {
             let newNode = new Node(val);
             if(!this.head) {
                 this.head = newNode;
                 this.tail = this.head;
             } else {
                 this.tail.next = newNode;
                 this.tail = newNode;
             }
             this.length++;
             return this;
         }
    

Pop: removing a node from the end of the linked list

  1. If there are no nodes in the linked list, return undefined.

  2. Loop through the list until you reach the tail.

  3. Set the next property of the second last node to be null.

  4. Set the tail to be the second last node.

  5. Decrement the length of the list by one.

  6. Return the value of the node removed.

     pop() {
             if(!this.head) return undefined;
             let current = this.head;
             let newTail = current;
             while(current.next) {
                 newTail = current;
                 current = current.next;
             }
    
             this.tail = newTail;
             this.tail.next = null;
             this.length--;
             if(this.length === 0) {
                 this.head = null;
                 this.tail = null;
             }
    
             return current;
         }
    

Unshift: adding a new node at the beginning of the linked list

  1. This function should accept a value.

  2. Create a new node using the value passed to the function.

  3. If there is no head property on the list, set the head and tail to be the newly created node.

  4. Otherwise set the newly created node’s next property to be the current head on the list.

  5. Set the head property on the list to be that newly created node.

  6. Increment the length of the list by one.

  7. Return the linked list.

     unshift(val) {
             let newNode = new Node(val);
             if(!this.head) {
                 this.head = newNode;
                 this.tail = newNode;
             } else {
                 newNode.next = this.head;
                 this.head = newNode;
             }
             this.length++;
             return this;
         }
    

Shift: removing a new node from the beginning of the linked list

  1. If there isn’t any node in the linked list, return undefined.

  2. Store the current head property in a variable.

  3. Set the head property to be the current head’s next property.

  4. Decrement the length by one.

  5. Return the value of the node removed.

     shift() {
             if(!this.head) return undefined;
             let currentHead = this.head;
             this.head = currentHead.next;
             this.length--;
             if(this.length === 0) {
                 this.tail = null;
             }
    
             return currentHead;
         }
    

Get: retrieving a node by its position in the linked list.

  1. The function should accept an index.

  2. If the index is less than zero or greater than or equal to the length of the list, return null.

  3. Loop through the list until you reach the index and return the node at that specific index.

     get(index) {
             if(index < 0 || index >= this.length) return null;
             let counter = 0;
             let current = this.head;
             while(counter !== index) {
                 current = current.next;
                 counter++;
             }
             return current;
         }
    

Set: changing the value of a node based on its position in the linked list.

  1. The function should accept a value and an index.

  2. Use the get function to find the specific node.

  3. If the node is not found, return false.

  4. If the node is found, set the value of that node to be the value passed to the function and return true.

     set(index, val) {
             var foundNode = this.get(index);
             if(foundNode) {
                 foundNode.val = val;
                 return true;
             }
             return false;
         }
    

Insert: adding a node to the linked list at a specific position

  1. If the index is less than zero or greater than the length, return false. (index < 0 || index > length)

  2. If the index is the same as the length, push a new node to the end of the list. (index == length)

  3. If the index is zero, unshift a new node to the start of the list. (index == 0)

  4. Otherwise, using the get method, access the node at the index-1.

  5. Set the next property on that node to be the new node.

  6. Set the next property on the new node to be the previous next.

  7. Increment the length.

  8. Return true.

     insert(index, val) {
    
             if(index < 0 || index > this.length) return false;
             if(index === this.length) return !! this.push(val);
             if(index === 0) return !! this.unshift(val);
    
             let newNode = new Node(val);
             let prev = this.get(index - 1);
             let temp = prev.next;
             prev.next = newNode;
             newNode.next = temp;
    
             this.length++;
             return true
         }
    

Remove: remove a node from the linked list at a specific position

  1. If the index is less than zero or greater than the length, return undefined. (index < 0 || index > length)

  2. If the index is the same as the length-1, pop. (index = length-1)

  3. If index = 0, shift.

  4. Otherwise using the get method, access the node at the index-1.

  5. Set the next property on that node to be the next of the next node.

  6. Decrement the length by one.

  7. Return the value of the node removed.

     remove(index) {
             if(index < 0 || index >= this.length) return undefined;
             if(index === 0) return this.shift();
             if(index === this.length - 1) return this.pop();
    
             var previousNode = this.get(index-1);
             var removed = previousNode.next;
             previousNode.next = removed.next;
             this.length--;
             return removed;
         }
    

Time Complexity of Singly Linked List:

  • Access: O(n)

  • Search: O(n)

  • Insertion: O(1)

  • Removal: O(1) (in some cases O(n))

Summary:

Singly Linked Lists are excellent alternatives to arrays when insertion and deletion at the beginning are frequently required.