Assumes understanding of Big O notation. Examples are in JavaScript. Information references "Cracking the Coding Interview" by Gayle Laakmann McDowell
A linked list is a data structure that represents a sequence of nodes. In a singly linked list, each node points to the next node.
In memory, these nodes do not need to be sorted contiguously (adjacent to one another) since we are not relying on indexing. When we iterate through a linked list, we pass through each reference of a node until we hit a null pointer.
In a singly linked list, each node typically contains two fields:
The head is a reference to the first node in the list. It is essential because it allows access to the linked list’s start. It sometimes acts as a sentinel node (placed before the actual head node) for easier operations like inserting at the head. The tail is a reference to the last node in the list. It’s next pointer is null indicating the end of the list.
Compared to arrays, linked lists are more memory efficient in terms of insertion/deletion since these operations do not require “shifting” of elements. The operation of adding or removing an element from anywhere in a linked list takes O(1) time. However, it takes O(n) time in the worst case to traverse through the linked list to then add/remove an element (does not apply for adding/removing first element).
It's worth pointing out that linked lists have extra memory overhead due to the storage of pointers along with data in each node.
Insertion:
Deletion:
Traversal/Search: O(n)
class ListNode { constructor(val, nextNode = null) { this.val = val; this.next = nextNode; } } class LinkedList { constructor() { // sentinel node for easy operations on head this.head = new ListNode(-1); this.tail = this.head; } // get the value at the specified index. get(index) { let curr = this.head.next; let i = 0; while (curr !== null) { if (i === index) return curr.val; curr = curr.next; i++; } return -1; } // insert a new value at the head of the list. insertHead(val) { const newNode = new ListNode(val); newNode.next = this.head.next; this.head.next = newNode; if (newNode.next === null) { this.tail = newNode; } } // insert a new value at the tail of the list. insertTail(val) { const newNode = new ListNode(val); this.tail.next = newNode; this.tail = newNode; } // remove the node at the specified index. remove(index) { let curr = this.head; let i = 0; while (i < index && curr.next !== null) { i++; curr = curr.next; } if (curr !== null && curr.next !== null) { if (curr.next === this.tail) this.tail = curr; curr.next = curr.next.next; return true; } return false; } // get all values in the list as an array. getValues() { const values = []; let curr = this.head.next; while (curr !== null) { values.push(curr.val); curr = curr.next; } return values; } // get the length of the list. length() { let length = 0; let curr = this.head.next; while (curr !== null) { length++; curr = curr.next; } return length; } }
function ListNode(val, nextNode = null) { this.val = val; this.next = nextNode; } function LinkedList() { this.head = new ListNode(-1); // Sentinel node this.tail = this.head; } // get the value at the specified index LinkedList.prototype.get = function(index) { let curr = this.head.next; let i = 0; while (curr !== null) { if (i === index) return curr.val; curr = curr.next; i++; } return -1; }; // insert a new value at the head of the list LinkedList.prototype.insertHead = function(val) { const newNode = new ListNode(val); newNode.next = this.head.next; this.head.next = newNode; if (newNode.next === null) { this.tail = newNode; } }; // insert a new value at the tail of the list LinkedList.prototype.insertTail = function(val) { const newNode = new ListNode(val); this.tail.next = newNode; this.tail = newNode; }; // remove the node at the specified index LinkedList.prototype.remove = function(index) { let curr = this.head; let i = 0; while (i < index && curr.next !== null) { i++; curr = curr.next; } if (curr !== null && curr.next !== null) { if (curr.next === this.tail) this.tail = curr; curr.next = curr.next.next; return true; } return false; }; // get all values in the list as an array LinkedList.prototype.getValues = function() { const values = []; let curr = this.head.next; while (curr !== null) { values.push(curr.val); curr = curr.next; } return values; }; // get the length of the list LinkedList.prototype.length = function() { let length = 0; let curr = this.head.next; while (curr !== null) { length++; curr = curr.next; } return length; };
The above is the detailed content of Implementing a Singly Linked List. For more information, please follow other related articles on the PHP Chinese website!