Back to DSA Course

DSA Course

A linked list is a liner data structure where each element is a separate object. Each element (node) of a list comprises of two items i.e. data and a reference to next node.

The most powerful feature of linked list is that it is of variable size.

Advantages

  • Dynamic nature.
  • Optimal insertion and deletion.
  • Stacks and Queues can be easily implemented.
  • No memory wastage.

DisAdvantages

  • More memory usage due to address pointer.
  • Slow traversal compared to Arrays.
  • No reverse traversal in singly linked list.
  • No random access.

Linked List vs Array

screenshot of the app

Linked List Components

  • Node: Contains both data and reference to next node
  • Head: Reference to first node in the list
  • Tail: Reference to last node in the list

Common Operations in Linked List

  • Creation of Linked List
  • Insertion of Linked List
  • Traversal of Linked List
  • Searching in a Linked List
  • Deletion of a node from Linked List
  • Deletion of Linked List

Types of Linked List

  • Single Linked List
  • Circular Single Linked List
  • Double Linked List
  • Circular Double Linked List

Singly Linked List

screenshot of the app

In a singly linked list, each node stores the data of the node and reference of the next node in the list. It doesn't store the reference of previous node.

It is the most basic form of linked list which give the flexibility to add/remove nodes at runtime.

For example, single linked list fails for multiplayer board game if we are tracking players turn in linked list.

Singly Linked List Operations

screenshot of the app

  • Accessing the head: O(1).
  • Accessing the tail: O(n).
  • Accessing a middle node: O(n).
  • Inserting or removing the head: O(1).
  • Inserting or removing the tail: O(n) to access + O(1).
  • Inserting or removing a middle node: O(n) to access + O(1).
  • Searching for a value: O(n).
package com.praveen.node; public class SingleNode { private int value; private SingleNode next; public int getValue() { return value; } public void setValue(int value) { this.value = value; } public SingleNode getNext() { return next; } public void setNext(SingleNode next) { this.next = next; } @Override public String toString() { return value + ""; } }
package com.praveen.linkedlist; import com.praveen.node.SingleNode; public class SingleLinkedList { private SingleNode head; private SingleNode tail; private int size;// denotes size of list public SingleNode createSingleLinkedList(int nodeValue) { head = new SingleNode(); SingleNode node = new SingleNode(); node.setValue(nodeValue); node.setNext(null); head = node; tail = node; size = 1;// size =1 return head; } public SingleNode getHead() { return head; } public void setHead(SingleNode head) { this.head = head; } public SingleNode getTail() { return tail; } public void setTail(SingleNode tail) { this.tail = tail; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } public void insertInLinkedList(int nodeValue, int location) { SingleNode node = new SingleNode(); node.setValue(nodeValue); if (!existsLinkedList()) { // Linked List does not exists System.out.println("The linked list does not exist!!"); return; } else if (location == 0) {// insert at first position node.setNext(head); head = node; } else if (location >= size) {// insert at last position node.setNext(null); tail.setNext(node); tail = node; } else {// insert at specified location SingleNode tempNode = head; int index = 0; while (index < location - 1) {// loop till we reach specified node tempNode = tempNode.getNext(); index++; } // tempNode currently references to node after which we should insert new node SingleNode nextNode = tempNode.getNext(); // this is the immediate next node after new node tempNode.setNext(node);// update reference of tempNode to reference to new node node.setNext(nextNode);// update newly added nodes' next. } setSize(getSize() + 1); } public boolean existsLinkedList() { // if head is not null retrun true otherwise return false return head != null; } // Traverses Linked List void traverseLinkedList() { if (existsLinkedList()) { SingleNode tempNode = head; for (int i = 0; i < getSize(); i++) { System.out.print(tempNode.getValue()); if (i != getSize() - 1) { System.out.print(" -> "); } tempNode = tempNode.getNext(); } } else { System.out.println("Linked List does not exists !"); } System.out.println("\n"); } // Deletes entire Linked List void deleteLinkedList() { System.out.println("\n\nDeleting Linked List..."); head = null; tail = null; System.out.println("Linked List deleted successfully !"); } // Searches a node with given value boolean searchNode(int nodeValue) { if (existsLinkedList()) { SingleNode tempNode = head; for (int i = 0; i < getSize(); i++) { if (tempNode.getValue() == nodeValue) { System.out.print("Found the node at location: " + i + "\n"); return true; } tempNode = tempNode.getNext(); } } System.out.print("Node not found!! \n"); return false; } // Deletes a node having a given value public void deletionOfNode(int location) { if (!existsLinkedList()) { System.out.println("The linked list does not exist!!");// Linked List does not exists return; } else if (location == 0) { // we want to delete first element head = head.getNext(); setSize(getSize() - 1); if (getSize() == 0) { // if there are no more nodes in this list tail = null; } } else if (location >= getSize()) { // If location is not in range or equal, then delete last node SingleNode tempNode = head; for (int i = 0; i < size - 1; i++) { tempNode = tempNode.getNext(); // temp node points to 2nd last node } if (tempNode == head) { // if this is the only element in the list tail = head = null; setSize(getSize() - 1); return; } tempNode.setNext(null); tail = tempNode; setSize(getSize() - 1); } else { // if any inside node is to be deleted SingleNode tempNode = head; for (int i = 0; i < location - 1; i++) { tempNode = tempNode.getNext(); // we need to traverse till we find the location } tempNode.setNext(tempNode.getNext().getNext()); // delete the required node setSize(getSize() - 1); } } }

Circular Singly Linked List

screenshot of the app

In case of circular singly linked list, the only change that occurs is that the end of the given list is linked back to the front.

For example, multiplayer board game if we are tracking players turn in linked list.

package com.praveen.linkedlist; import com.praveen.node.SingleNode; public class SingleCircularLinkedList { private SingleNode head; private SingleNode tail; private int size;// denotes size of list SingleNode createSingleLinkedList(int nodeValue) { head = new SingleNode(); SingleNode node = new SingleNode(); node.setValue(nodeValue); node.setNext(node); head = node; tail = node; size = 1;// size =1 return head; } public SingleNode getHead() { return head; } public void setHead(SingleNode head) { this.head = head; } public SingleNode getTail() { return tail; } public void setTail(SingleNode tail) { this.tail = tail; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } void insertInLinkedList(int nodeValue, int location) { SingleNode node = new SingleNode(); node.setValue(nodeValue); System.out.println("Inserting new node at location: " + location); if (!existsLinkedList()) { System.out.println("The linked list does not exist!!"); return; // Linked List does not exists } else if (location == 0) {// insert at first position node.setNext(head); head = node; tail.setNext(node); // update tail } else if (location >= size) {// insert at last position tail.setNext(node); tail = node; // to keep track of last node tail.setNext(head); // update tail to circularly point head } else // insert at specified location { SingleNode tempNode = head; int index = 0; while (index < location - 1) {// loop till we reach specified node tempNode = tempNode.getNext(); index++; } // insert new node after tempNode node.setNext(tempNode.getNext()); tempNode.setNext(node); } size++; } public boolean existsLinkedList() { // if head is not null retrun true otherwise return false return head != null; } // Traverse Linked List void traverseLinkedList() { if (existsLinkedList()) { SingleNode tempNode = head; for (int i = 0; i < size; i++) { System.out.print(tempNode.getValue()); if (i != size - 1) { System.out.print(" -> "); } tempNode = tempNode.getNext(); } System.out.println("\n"); } else { System.out.println("\nLinked List does not exists !"); } } // Traverse Linked List void printHeadUsingTail() { if (existsLinkedList()) { System.out.println("Printing Tail..."); System.out.println(tail.getValue()); System.out.println("Printing Head using Head reference..."); System.out.println(head.getValue()); System.out.println("Printing Head using Tail reference..."); System.out.println(tail.getNext().getValue()); } else { System.out.println("Linked List does not exists"); } } // Delete linked list void deleteLinkedList() { System.out.println("\n\nDeleting Linked List..."); head = null; if (tail == null) { System.out.println("Linked List is already deleted, nothing to delete !"); return; } else { tail.setNext(null); tail = null; System.out.println("Linked List deleted successfully !"); } } // Search given value in Linked List boolean searchNode(int nodeValue) { if (existsLinkedList()) { SingleNode tempNode = head; for (int i = 0; i < size; i++) { // System.out.print(tempNode.value); if (tempNode.getValue() == nodeValue) { System.out.print("Found the node at location: " + i); return true; } tempNode = tempNode.getNext(); } } System.out.print("Node not found!! "); return false; } public void deletionOfNode(int location) { if (!existsLinkedList()) { System.out.println("The linked list does not exist!!");// Linked List does not exists return; } else if (location == 0) { // we want to delete first element head = head.getNext(); tail.setNext(head); setSize(getSize() - 1); if (getSize() == 0) { // if there are no more nodes in this list tail = null; } } else if (location >= getSize()) { // If location is not in range or equal, then delete last node SingleNode tempNode = head; for (int i = 0; i < size - 1; i++) { tempNode = tempNode.getNext(); // temp node points to 2nd last node } if (tempNode == head) { // if this is the only element in the list tail = head = null; setSize(getSize() - 1); return; } tempNode.setNext(head); tail = tempNode; setSize(getSize() - 1); } else { // if any inside node is to be deleted SingleNode tempNode = head; for (int i = 0; i < location - 1; i++) { tempNode = tempNode.getNext(); // we need to traverse till we find the location } tempNode.setNext(tempNode.getNext().getNext()); // delete the required node setSize(getSize() - 1); } } }

Doubly Linked List

screenshot of the app

In case of double linked list each node contains previous and next node references.

This is useful when we want to move in both direction depending on requirement.

For example, Music player has next and previous buttons.

Doubly Linked List Operations

  • Accessing the head: O(1).
  • Accessing the tail: O(1).
  • Accessing a middle node: O(n).
  • Inserting or removing the head: O(1).
  • Inserting or removing the tail: O(1).
  • Inserting or removing a middle node: O(n) to access + O(1).
  • Searching for a value: O(n).
package com.praveen.linkedlist; import com.praveen.node.DoubleNode; public class DoubleLinkedList { DoubleNode head; DoubleNode tail; int size;// denotes size of list public int getSize() { return size; } public void setSize(int size) { this.size = size; } DoubleNode createDoubleLinkedList(int nodeValue) { head = new DoubleNode(); DoubleNode node = new DoubleNode(); node.setValue(nodeValue); node.setNext(null); node.setPrev(null); head = node; tail = node; size = 1;// size =1 return head; } void insertInLinkedList(int nodeValue, int location) { DoubleNode node = new DoubleNode(); node.setValue(nodeValue); if (!existsLinkedList()) { System.out.println("The linked list does not exist!!"); return; // Linked List does not exists } else if (location == 0) {// insert at first position node.setNext(head); node.setPrev(null); head.setPrev(node); head = node; } else if (location >= size) {// insert at last position node.setNext(null); tail.setNext(node); node.setPrev(tail); tail = node; // to keep track of last node } else {// insert at specified location DoubleNode tempNode = head; int index = 0; while (index < location - 1) {// loop till we reach specified node tempNode = tempNode.getNext(); index++; } node.setPrev(tempNode); node.setNext(tempNode.getNext()); tempNode.setNext(node); node.getNext().setPrev(node); } size++; } public boolean existsLinkedList() { // if head is not null retrun true otherwise return false return head != null; } // Traverse the linked list from head to last void traverseLinkedList() { if (existsLinkedList()) { // System.out.println("Linked List now: "); DoubleNode tempNode = head; for (int i = 0; i < size; i++) { System.out.print(tempNode.getValue()); if (i != size - 1) { System.out.print(" -> "); } tempNode = tempNode.getNext(); } } else { System.out.println("Linked List does not exists"); } System.out.println("\n"); } // Traverse the linked list from head to last void traverseLinkedListInReverseOrder() { if (existsLinkedList()) { DoubleNode tempNode = tail; for (int i = 0; i < size; i++) { System.out.print(tempNode.getValue()); if (i != size - 1) { System.out.print(" <- "); } tempNode = tempNode.getPrev(); } } else { System.out.println("Linked List does not exists"); } System.out.println("\n"); } // delete whole linked list void deleteLinkedList() { System.out.println("\n\nDeleting Linked List..."); DoubleNode tempNode = head; for (int i = 0; i < size; i++) { tempNode.setPrev(null); tempNode = tempNode.getNext(); } head = null; tail = null; System.out.println("Linked List deleted successfully !"); } // Search for a node in linked list boolean searchNode(int nodeValue) { if (existsLinkedList()) { DoubleNode tempNode = head; for (int i = 0; i < size; i++) { if (tempNode.getValue() == nodeValue) { System.out.print("Found the node at locaiton: " + i); return true; } tempNode = tempNode.getNext(); } } System.out.print("Node not found!! "); return false; } // Deletes a node having a given value public void deletionOfNode(int location) { if (!existsLinkedList()) { System.out.println("The linked list does not exist!!");// Linked List does not exists return; } else if (location == 0) { // we want to delete first element if (getSize() == 1) { // if this is the only node in this list head = tail = null; setSize(getSize() - 1); return; } else { head = head.getNext(); head.setPrev(null); setSize(getSize() - 1); } } else if (location >= getSize()) { // If location is not in range or equal, then delete last node DoubleNode tempNode = tail.getPrev(); // temp node points to 2nd last node if (tempNode == head) { // if this is the only element in the list tail = head = null; setSize(getSize() - 1); return; } tempNode.setNext(null); tail = tempNode; setSize(getSize() - 1); } else { // if any inside node is to be deleted DoubleNode tempNode = head; for (int i = 0; i < location - 1; i++) { tempNode = tempNode.getNext(); // we need to traverse till we find the location } tempNode.setNext(tempNode.getNext().getNext()); // delete the required node tempNode.getNext().setPrev(tempNode); setSize(getSize() - 1); } } }

Circular Doubly Linked List

screenshot of the app

In case of circular doubly single linked list, the only change that occurs is that the end of the given list is linked back to the front of the list and vice versa.

This is useful when we want to loop through the list indefinitely until the list exists. We want to move both forward and backward.

For example, ALT+TAB button in Windows.

package com.praveen.linkedlist; import com.praveen.node.DoubleNode; public class DoubleCircularLinkedList { private DoubleNode head; private DoubleNode tail; private int size;// denotes size of list public int getSize() { return size; } public void setSize(int size) { this.size = size; } DoubleNode createDoubleLinkedList(int nodeValue) { head = new DoubleNode(); DoubleNode node = new DoubleNode(); node.setValue(nodeValue); node.setNext(node); node.setPrev(node); head = node; tail = node; size = 1;// size =1 return head; } public DoubleNode getHead() { return head; } public void setHead(DoubleNode head) { this.head = head; } public DoubleNode getTail() { return tail; } public void setTail(DoubleNode tail) { this.tail = tail; } public int getLast() { return size; } public void setLast(int last) { this.size = last; } void insertInLinkedList(int nodeValue, int location) { DoubleNode node = new DoubleNode(); node.setValue(nodeValue); if (!existsLinkedList()) { System.out.println("The linked list does not exist!!"); return; // Linked List does not exists } else if (location == 0) {// insert at first position node.setNext(head); node.setPrev(tail); head.setPrev(node); tail.setNext(node); head = node; } else if (location >= size) { // insert at last position node.setNext(head); node.setPrev(tail); head.setPrev(node); tail.setNext(node); tail = node; // to keep track of last node } else {// insert at specified location DoubleNode tempNode = head; int index = 0; while (index < location - 1) {// loop till we reach specified node tempNode = tempNode.getNext(); index++; } node.setPrev(tempNode); node.setNext(tempNode.getNext()); tempNode.setNext(node); node.getNext().setPrev(node); } size++;// one node added so size increments } public boolean existsLinkedList() { // if head is not null retrun true otherwise return false return head != null; } // Traverse Linked List void traverseLinkedList() { if (existsLinkedList()) { DoubleNode tempNode = head; for (int i = 0; i < size; i++) { System.out.print(tempNode.getValue()); if (i != size - 1) { System.out.print(" -> "); } tempNode = tempNode.getNext(); } } else { System.out.println("Linked List does not exists !"); } System.out.println(); } // Traverse Linked List reverse order void traverseLinkedListInReverseOrder() { if (existsLinkedList()) { DoubleNode tempNode = tail; System.out.println("\nPrinting Linked list in reverse order..."); for (int i = 0; i < size; i++) { System.out.print(tempNode.getValue()); if (i != size - 1) { System.out.print(" <- "); } tempNode = tempNode.getPrev(); } } else { System.out.println("Linked List does not exists !"); } } // Traverse Linked List void printHeadUsingTail() { if (existsLinkedList()) { System.out.println("\n\nPrinting Tail..."); System.out.println(tail.getValue()); System.out.println("\nPrinting Head using Head reference..."); System.out.println(head.getValue()); System.out.println("\nPrinting Head using Tail reference..."); System.out.println(tail.getNext().getValue()); } else { System.out.println("Linked List does not exists"); } } // Deletion of linked list void deleteLinkedList() { System.out.println("\n\nDeleting Linked List..."); if (tail == null) { System.out.println("Linked List is already deleted, nothing to delete anymore !"); return; } else { head.setPrev(null); tail.setNext(null); head = null; tail = null; System.out.println("Linked List deleted successfully !"); } } // Searching a specified value in linked list boolean searchNode(int nodeValue) { if (existsLinkedList()) { DoubleNode tempNode = head; traverseLinkedList(); for (int i = 0; i < size; i++) { if (tempNode.getValue() == nodeValue) { System.out.print("Found the node at location: " + i); return true; } tempNode = tempNode.getNext(); } } System.out.print("Node not found!! "); return false; } // Deletes a node having a given value public void deletionOfNode(int location) { if (!existsLinkedList()) { System.out.println("The linked list does not exist!!");// Linked List does not exists return; } else if (location == 0) { // we want to delete first element if (getSize() == 1) { // if this is the only node in this list head.setNext(null); head.setPrev(null); head = tail = null; setSize(getSize() - 1); return; } else { head = head.getNext(); head.setPrev(null); tail.setNext(head); setSize(getSize() - 1); } } else if (location >= getSize()) { // If location is not in range or equal, then delete last node if (getSize() == 1) { // if this is the only element in the list head.setNext(null); head.setPrev(null); tail = head = null; setSize(getSize() - 1); return; } tail = tail.getPrev(); tail.setNext(head); head.setPrev(tail); setSize(getSize() - 1); } else { // if any inside node is to be deleted DoubleNode tempNode = head; for (int i = 0; i < location - 1; i++) { tempNode = tempNode.getNext(); // we need to traverse till we find the location } tempNode.setNext(tempNode.getNext().getNext()); // delete the required node tempNode.getNext().setPrev(tempNode); setSize(getSize() - 1); } } }

How is Linked List stored in memory(RAM)?

As you see the below diagram, In Linked List cells will not be stored in contiguous memory location like an Array and it stores in uneven location.

Linked List Applications

  • Dynamic memory allocation
  • Implemented in stack and queue
  • In undo functionality of softwares
  • Hash tables, Graphs