Skip to main content

Linked Lists

  • it is a data structure in which the objects are arranged in a linear order
  • order in a linked list is determined by a pointer in each object
  • consists of nodes, each with some value and a pointer to the next node in the linked list
  • a linked list node's value and next node are typically stored in value and next properties
  • the 1st node in a linked list is referred to as the head of the linked list
  • the last node in a linked list, whose next property points to the null value is known as the tail of the linked list
  • linked lists differs from an array is in how it's implemented and how it's stored in memory
    • basically it would store each node (1 memory slot) with their pointer (1 memory slot) back to back
      • the pointer stores the memory address of the next node
      • each node and their respective pointers are not stored back to back with the other nodes and pointers in the memory
      • they are linked together via their pointers
      • in the case of a singly linked list, the last node would point to the memory address that contains the null value
  • The advantage of this data structure is usage of pointers
    • In languages with manual memory allocation this allows data structures to allocate memory dynamically
    • In javascript, this advantage is mitigated in general, but other features of a double linked list could be used
class Node<T> {
constructor(public element: T, public next?: Node<T>) {}
}
class DoublyNode<T> extends Node<T> {
constructor(
public element: T,
public next?: DoublyNode<T>,
public prev?: DoublyNode<T>
) {
super(element, next);
}
}

Singly Linked List

Linked list

  • visual representation of a singly linked list whose nodes hold integer values
    • 0 -> 1 -> 2 -> 3 -> null
  • a singly linked list typically exposes its head to its user for easy access
    • while finding a node in a singly linked list involves traversing through all of the nodes leading up to the node in question (as opposed to instant access with an array)
      • adding or removing nodes involves overwriting next pointers (assuming that you have access to the node right before the node that you're adding or removing)

standard operations and their complexities

Initialize a linked list: O(n) time, O(n) space

  • this will create 2n memory slots, 1 for the node and 1 for the pointer
  • it will also need to allocate the n chunks of memory thus will take n time

Accessing the head: O(1) time, O(1) space

  • space is not affected

Accessing the tail: O(n) time, O(1) space

  • requires to traverse the linked list to get the node
  • space is not affected

Accessing a middle node: O(n) time, O(1) space

  • requires to traverse the linked list to get the node
  • space is not affected

Inserting / Removing the head: O(1) time, O(1) space

  • none of the nodes are required to be shifted, therefore it only requires changing of the head reference which is only for 1 node making it constant time and space effort
  • With add operation, memory is allocated for a new node and then the pointer in the last element is updated to point to the new node.

Inserting / Removing the tail: O(n) to access + O(1) to modify time, O(1) space

  • requires traversing through the list before any changing of reference could be done, therefore time is linear to traverse but modification is constant

Inserting / Removing a middle node: O(n) to access + O(1) to modify time, O(1) space

  • requires traversing through the list before any changing of reference could be done, therefore time is linear to traverse but modification is constant

Searching for a value: O(n) time, O(1) space

Traverse a linked list: O(n) time, O(1) space

  • space is not affected

Copy a linked list: O(n) time, O(n) space

Doubly Linked List

Double linked list

  • similar to a singly linked list, except that each node in a doubly linked list also has a pointer to the previous node
    • the previous node is typically stored in a prev property
  • just as the next property of a doubly linked list's tail points to the null value, the prev property of a doubly linked list head also points to the null value
  • visual representation of a doubly linked list whose nodes hold integer values
    • null <-> 0 <-> 1 <-> 2 <-> 3 <-> null
  • a doubly linked list typically exposes both its head and tail to its user
    • it also behaves very similarly to a singly linked list

standard operations and their time complexities

Initialize a linked list: O(n) time, O(n) space

  • this will create 2n memory slots, 1 for the node and 1 for the pointer
  • it will also need to allocate the n chunks of memory thus will take n time

Accessing the head: O(1) time, O(1) space

Accessing the tail: O(1) time, O(1) space

Accessing a middle node: O(n) time, O(1) space

Inserting / Removing the head: O(1) time, O(1) space

Inserting / Removing the tail: O(1) time, O(1) space

Inserting / Removing a middle node: O(n) to access + O(1) to modify time, O(1) space

Searching for a value: O(n) time, O(1) space

Traverse a linked list: O(n) time, O(1) space

  • space is not affected

Copy a linked list: O(n) time, O(n) space

Circular Linked List / Cyclic Linked List

Cyclic linked list

  • a linked list that has no clear head or tail
    • because its tail points to its head
    • forming a closed circle
  • it can be either singly circular linked list or a doubly circular linked list

Circular Double Linked List / Cyclic Double Linked List

Cyclic double linked list

  • the last element is pointing to the first and first points to the last