Summary
Name | Singly Linked List |
Type | Linked List |
Use cases | |
Related Data Structures | Doubly Linked List Tree |
Definition
A singly linked list is a list of items, where each element has reference to the next element. Elements do not have info on the previous element. So we can only go to the next element while traversing a singly linked list.

NOTE
Check the link below to check the details of Linked List and Singly Linked List-
Use Cases
Implementation
Here is the detailed implementation of Singly Linked List in JavaScript and TypeScript, step-by-step –
Step #1: Node Class
The purpose of the Node class is to store information on a single node. It stores data and references to the next node.

// Node class for storing data
// and reference to the next node
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
JavaScript NOTE
For TypeScript we are using a generic and passing the type as <T>. This “T” type will be the type of data.
This is used to provide flexibility in storing any type of data in the list.
You can assign a fixed type to the data, if you are going to use the list implementation for a specific single purpose.
// Node class for storing data
// and reference to the next node
class Node<T> {
data: T;
next: Node<T> | null;
constructor(data: T) {
this.data = data;
this.next = null;
}
}
TypeScriptclass Node {
public ?Node $next = null;
public function __construct(public string $data) {
}
}
PHPclass Node:
def __init__(self, data):
self.data = data
self.next = None
PythonStep #2: Linked List Class
The lined list class is the place where are implementing the actual linked list-

// Singly Linked List class
class SinglyLinkedList {
constructor() {
this.head = null;
this.tail = null;
this.length = 0;
}
}
JavaScript// Singly Linked List class
class SinglyLinkedList<T> {
public head: Node<T> | null;
public tail: Node<T> | null;
public length: number;
constructor() {
// Initialize head, tail, and length
this.head = null;
this.tail = null;
this.length = 0;
}
}
TypeScriptclass SinglyLinkedList {
public ?Node $head = null;
public ?Node $tail = null;
public int $length = 0;
public function __construct() {
}
}
PHPclass SinglyLinkedList:
def __init__(self):
self.head = None
self.tail = None
self.length = 0
Python NOTE
For TypeScript we are using a generic and passing the type as <T>. We need to pass this type <T> to the “Node” item.
Step #3: Push (Node to the end)

class SinglyLinkedList<T> {
//...
push(data: T): SinglyLinkedList<T> {
// Add data at the end of the list
const node = new Node(data);
if (!this.head) {
// If list is empty, set head and tail to new node
this.head = node;
} else {
// Otherwise, set the next of current tail to new node
this.tail!.next = node;
}
// Set new node as the tail
this.tail = node;
// Increase the length
this.length++;
return this;
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
push(data: T): SinglyLinkedList<T> {
// Add data at the end of the list
const node = new Node(data);
if (!this.head) {
// If list is empty, set head and tail to new node
this.head = node;
} else {
// Otherwise, set the next of current tail to new node
this.tail!.next = node;
}
// Set new node as the tail
this.tail = node;
// Increase the length
this.length++;
return this;
}
//...
}
TypeScriptclass SinglyLinkedList {
// ...
// Push node to the end of the list
public function push(string $data): bool {
$node = new Node($data);
// If the list is empty
// then make this node as head and tail
if ($this->head === null) {
$this->head = $node;
} else {
// set the current tail's next value to new node
$this->tail->next = $node;
}
// Set the tail to this new node
$this->tail = $node;
// Increase the length by 1
$this->length++;
return true;
}
// ...
}
PHPclass SinglyLinkedList:
# Other functionality
# Push item to the end
def push(self, data):
# Create a new node
node = Node(data)
# If there is no head, that means the list is empty
# Then make this new node as head
if not self.head:
self.head = node
else:
# Set the new node as the next of the current tail
self.tail.next = node
# Set the new node as tail
self.tail = node
# Increase length by 1
self.length += 1
PythonStep #4: Pop (Last Node)

class SinglyLinkedList {
//...
// Pop the last item
pop() {
// If there is no head
// then the list does not exist
if (!this.head) {
return null;
}
let current = this.head;
let newTail = current;
// Traverse through the list
// and get the second last item as newTail
while (current.next) {
newTail = current;
current = current.next;
}
// Assign the newTail to the tail
this.tail = newTail;
// Delete the next pointer of the tail
this.tail.next = null;
this.length--;
// Reset head and tail if it was the last item
if (this.length == 0) {
this.head = null;
this.tail = null;
}
// Return the popped item
return current;
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
pop(): Node<T> | null {
// Remove and return the last element from the list
if (!this.head) {
// If list is empty, return null
return null;
}
let current = this.head;
let newTail = current;
while (current.next) {
// Traverse the list to find the second last node
newTail = current;
current = current.next;
}
// Update tail and remove the last node
this.tail = newTail;
this.tail.next = null;
this.length--;
if (this.length === 0) {
// If list becomes empty, reset head and tail
this.head = null;
this.tail = null;
}
return current;
}
//...
}
TypeScriptclass SinglyLinkedList {
// ...
// Pop the last item
public function pop(): ?Node {
// If there is no head
// then the list does not exist
if ($this->head === null) {
return null;
}
$current = $this->head;
$newTail = $current;
// Traverse through the list
// and get the second last item as newTail
while ($current->next !== null) {
$newTail = $current;
$current = $current->next;
}
// Assign the newTail to the tail
$this->tail = $newTail;
// Delete the next pointer of the tail
$this->tail->next = null;
$this->length--;
// Reset head and tail if it was the last item
if ($this->length == 0) {
$this->head = null;
$this->tail = null;
}
// Return the popped item
return $current;
}
// ...
}
PHPclass SinglyLinkedList:
# Other functionality
# Pop item from the end
def pop(self):
# Return None if the list is empty
if not self.head:
return None
current = self.head
new_tail = current
# Traverse through the list
# and get the second last item as new_tail
while current.next:
new_tail = current
current = current.next
# Set the new tail
self.tail = new_tail
# Set next of the new tail as None
self.tail.next = None
# Decrease the length by 1
self.length -= 1
# If there is no item left
# then set the head and tail both as None
if self.length == 0:
self.head = None
self.Tail = None
# Return the node in the current variable
return current
PythonStep #5: Traverse all Nodes
class SinglyLinkedList<T> {
//...
traverse(): void {
// Traverse the list and log the data of each node
let current = this.head;
while (current) {
console.log(current.data);
current = current.next;
}
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
traverse(): void {
// Traverse the list and log the data of each node
let current = this.head;
while (current) {
console.log(current.data);
current = current.next;
}
}
//...
}
TypeScriptclass SinglyLinkedList {
// ...
// Traverse the list
public function traverse(): void {
$current = $this->head;
while ($current !== null) {
echo $current->data . PHP_EOL;
// Change current to the next node
$current = $current->next;
}
}
// ...
}
PHPclass SinglyLinkedList:
# Other functionality
def traverse(self):
current = self.head
while current:
print(current.data, end=" -> ")
# Move to the next node
current = current.next
PythonStep #6: Shift Head
class SinglyLinkedList {
//...
// Shift head
// and make the second item as head
// also return the first item
shift() {
// If there is no head then return null
if (!this.head) {
return null;
}
const currHead = this.head;
// Set the second item as head
this.head = currHead.next;
// Reduce the length by one
this.length--;
if (this.length === 0) {
this.head = null;
this.tail = null;
}
// Return the head item
return currHead;
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
shift(): Node<T> | null {
// Remove and return the first element from the list
if (!this.head) {
// If list is empty, return null
return null;
}
const currHead = this.head;
// Move head to the next node
this.head = currHead.next;
this.length--;
if (this.length === 0) {
// If list becomes empty, reset head and tail
this.head = null;
this.tail = null;
}
return currHead;
}
//...
}
TypeScriptclass SinglyLinkedList {
// ...
// Shift head
// and make the second item as head
// also return the first item
public function shift(): ?Node {
// If there is no head then return null
if ($this->head === null) {
return null;
}
$oldHead = $this->head;
// Set the second item as head
$this->head = $oldHead->next;
// Reduce the length by one
$this->length--;
if ($this->length === 0) {
$this->head = null;
$this->tail = null;
}
// Return the head item
return $oldHead;
}
// ...
}
PHPclass SinglyLinkedList:
# Other functionality
# Shift the head
# and maek the second item as the head
# Return the first item as result of shift
def shift(self):
# If the current head is None,
# then return None
if self.head is None:
return None
old_head = self.head
# Set the next node as head
self.head = old_head.next
# Decrease the length by 1
self.length -= 1
if self.length == 0:
self.tail = None
# Set the next of old_head to None
# and return the old_head
old_head.next = None
return old_head
PythonStep #7: Unshift Head
class SinglyLinkedList<T> {
//...
unshift(value: T): SinglyLinkedList<T> {
// Add data at the beginning of the list
let newHead = new Node(value);
if (!this.head) {
// If list is empty, set head and tail to new node
this.tail = newHead;
} else {
// Otherwise, set the next of new node to current head
newHead.next = this.head;
}
// Set new node as the head
this.head = newHead;
// Increase the length
this.length++;
return this;
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
unshift(value: T): SinglyLinkedList<T> {
// Add data at the beginning of the list
let newHead = new Node(value);
if (!this.head) {
// If list is empty, set head and tail to new node
this.tail = newHead;
} else {
// Otherwise, set the next of new node to current head
newHead.next = this.head;
}
// Set new node as the head
this.head = newHead;
// Increase the length
this.length++;
return this;
}
//...
}
TypeScriptclass SinglyLinkedList {
// ...
// Unshift head
// Create new node and set that as head
public function unshift($value): bool {
// Create new Node from value
$newHead = new Node($value);
if ($this->head === null) {
$this->tail = $newHead;
} else {
$newHead->next = $this->head;
}
// Set the new node as head
$this->head = $newHead;
// Increase length by one
$this->length++;
return true;
}
// ...
}
PHPclass SinglyLinkedList:
# Other functionality
# Unshift head
# Create new node and set that as head
def unshift(self, data):
# Create a new node from provided data
new_head = Node(data)
if self.head is None:
self.tail = new_head
else:
new_head.next = self.head
# Set the new_head as head of the list
self.head = new_head
# Increase size of the list by 1
self.length += 1
return new_head
PythonStep #8: Get Node by Index
We want to pass some index and want to get the node at that index-
class SinglyLinkedList {
//...
// Get node by index(sequence numbers)
// 0 based index (index starts from 0)
get(index) {
// Check if the index is valid
if (index < 0 || index >= this.length) {
return null;
}
let selectedNode = this.head;
for (let i = 1; i <= index; i++) {
selectedNode = selectedNode.next;
}
return selectedNode;
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
get(index: number): Node<T> | null {
// Get node at a specified index
if (index < 0 || index >= this.length) {
// If index is out of range, return null
return null;
}
let selectedNode = this.head;
for (let i = 1; i <= index; i++) {
// Traverse the list to find the node at the given index
selectedNode = selectedNode!.next;
}
return selectedNode;
}
//...
}
TypeScriptclass SinglyLinkedList {
// ...
// Get node by index(sequence numbers)
// 0 based index (index starts from 0)
public function get(int $index): ?Node {
// Check if the index is valid
if ($index < 0 || $index >= $this->length) {
return null;
}
$selectedNode = $this->head;
for ($i = 1; $i <= $index; $i++) {
$selectedNode = $selectedNode->next;
}
return $selectedNode;
}
// ...
}
PHPclass SinglyLinkedList:
# Other functionality
# Get node by index(sequence numbers)
# 0 based index (index starts from 0)
def get(self, index):
# Check if provided inex is valid
# Return None if index is invalid
if index < 0 or index >= self.length:
return None
selected_node = self.head
# Start from head and go till the provided index
for _ in range(index):
selected_node = selected_node.next
return selected_node
PythonStep #9: Search by data
Here we want to search for specific data. Whichever node has the data, we want to get that index.
class SinglyLinkedList {
//...
// Search the list for specific data
search(data) {
let current = this.head;
let index = 0;
while (current) {
if (current.data === data) {
return index;
}
current = current.next;
index++;
}
return null;
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
search(data: T): number | null {
// Search for the index of a specific data in the list
let current = this.head;
let index = 0;
while (current) {
// Traverse the list and check data of each node
if (current.data === data) {
// If data is found, return its index
return index;
}
current = current.next;
index++;
}
// If data is not found, return null
return null;
}
//...
}
TypeScriptclass SinglyLinkedList {
// ...
// Search the list for specific data
public function search(string $data): ?int {
$current = $this->head;
$index = 0;
while ($current) {
if ($current->data === $data) {
return $index;
}
$current = $current->next;
$index++;
}
return null;
}
// ...
}
PHPStep #10: Set data at Node by Index
Here we want to set the data of an existing, at a specific index.
class SinglyLinkedList<T> {
//...
set(index: number, data: T): boolean {
// Set data of a specific node at a given index
let nodeAtIndex = this.get(index);
if (nodeAtIndex) {
// If node at given index exists, update its data
nodeAtIndex.data = data;
return true;
}
// If node at given index does not exist, return false
return false;
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
set(index: number, data: T): boolean {
// Set data of a specific node at a given index
let nodeAtIndex = this.get(index);
if (nodeAtIndex) {
// If node at given index exists, update its data
nodeAtIndex.data = data;
return true;
}
// If node at given index does not exist, return false
return false;
}
//...
}
TypeScriptclass SinglyLinkedList {
// ...
// Set data of a specific node at specific index
// 0 based index(index starts from 0)
public function set(int $index, string $data): bool {
$nodeAtIndex = $this->get($index);
if ($nodeAtIndex) {
$nodeAtIndex->data = $data;
return true;
}
return false;
}
// ...
}
PHPclass SinglyLinkedList:
# Other functionality
# Search the list for specific data
def search(self, data):
current = self.head
index = 0
while current:
if current.data == data:
return index
current = current.next
index += 1
return None
PythonStep #11: Insert Data at Specific Index
We want to create a new node with data, and add that to some specific index.
class SinglyLinkedList<T> {
//...
insert(index: number, data: T): boolean {
// Insert new node at a specific index
if (index < 0 || index > this.length) {
// If index is out of range, return false
return false;
}
if (index === this.length) {
// If index is at the end, use push method
this.push(data);
return true;
}
if (index === 0) {
// If index is at the beginning, use unshift method
this.unshift(data);
return true;
}
// Otherwise, insert new node at the specified index
let newNode = new Node(data);
let prevNode = this.get(index - 1);
newNode.next = prevNode!.next;
prevNode!.next = newNode;
// Increase length
this.length++;
return true;
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
insert(index: number, data: T): boolean {
// Insert new node at a specific index
if (index < 0 || index > this.length) {
// If index is out of range, return false
return false;
}
if (index === this.length) {
// If index is at the end, use push method
this.push(data);
return true;
}
if (index === 0) {
// If index is at the beginning, use unshift method
this.unshift(data);
return true;
}
// Otherwise, insert new node at the specified index
let newNode = new Node(data);
let prevNode = this.get(index - 1);
newNode.next = prevNode!.next;
prevNode!.next = newNode;
// Increase length
this.length++;
return true;
}
//...
}
class SinglyLinkedList {
// ...
// Insert new node at a specific index
// 0 based index(index starts at 0)
public function insert(int $index, string $data): bool {
if ($index < 0 || $index > $this->length) {
return false;
}
if ($index === $this->length) {
$this->push($data);
return true;
}
if ($index === 0) {
$this->unshift($data);
return true;
}
$newNode = new Node($data);
$prevNode = $this->get($index - 1);
$newNode->next = $prevNode->next;
$prevNode->next = $newNode;
// Increase length
$this->length++;
return true;
}
// ...
}
PHPclass SinglyLinkedList:
# Other functionality
# Insert new node at a specific index
# 0 based index(index starts at 0)
def insert(self, index, data):
# Return false if index is out of range
if index < 0 or index > self.length:
return False
# If index is the next element after tail
# then just push item to the lsit
if index == self.length:
self.push(data)
return True
# If index is zero then unshift
if index == 0:
self.unshift(data)
return True
# Create new node and add it to the defined index
new_node = Node(data)
# Get the node after which this new node will be inserted
prev_node = self.get(index - 1)
# Add the new_node after the prev_node
new_node.next = prev_node.next
prev_node.next = new_node
# Increase length by one
self.length += 1
return True
PythonStep #12: Remove Item from Specific Index
class SinglyLinkedList {
//...
// Remove item at index
remove(index) {
// Return false if index is out of range
if (index < 0 || index >= this.length) {
return undefined;
}
if (index === 0) {
return this.shift();
}
if (index === this.length - 1) {
return this.pop();
}
let prevNode = this.get(index - 1);
const removedNode = prevNode.next;
prevNode.next = prevNode.next.next;
this.length--;
return removedNode;
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
remove(index: number): Node<T> | null {
// Remove node at a specific index
if (index < 0 || index >= this.length) {
// If index is out of range, return undefined
return null;
}
if (index === 0) {
// If index is at the beginning, use shift method
return this.shift();
}
if (index === this.length - 1) {
// If index is at the end, use pop method
return this.pop();
}
// Otherwise, remove node at the specified index
let prevNode = this.get(index - 1);
const removedNode = prevNode!.next;
prevNode!.next = prevNode!.next!.next;
// Decrease length
this.length--;
return removedNode;
}
//...
}
TypeScriptclass SinglyLinkedList {
// ...
// Remove item at index
public function remove(int $index): ?Node {
// Return false if index is out of range
if ($index < 0 || $index >= $this->length) {
return null;
}
if ($index === 0) {
return $this->shift();
}
if ($index === ($this->length - 1)) {
return $this->pop();
}
$prevNode = $this->get($index - 1);
$removedNode = $prevNode->next;
$prevNode->next = $prevNode->next->next;
$this->length--;
return $removedNode;
}
// ...
}
PHPclass SinglyLinkedList:
# Other functionality
# Reemove item at specific index
def remove(self, index):
# Return false if index is out of range
if index < 0 or index >= self.length:
return None
if index == 0:
return self.shift()
if index == self.length - 1:
return self.pop()
prev_node = self.get(index - 1)
node_to_remove = prev_node.next
prev_node.next = prev_node.next.next
# Decrease length by 1
self.length -= 1
return node_to_remove
PythonStep #13: Reverse a Singly Linked List
class SinglyLinkedList<T> {
//...
reverse(): SinglyLinkedList<T> {
// Reverse the linked list
let currentNode = this.head;
let prevNode = null;
let nextNode = null;
while (currentNode) {
// Traverse the list and reverse each node
nextNode = currentNode.next;
currentNode.next = prevNode;
prevNode = currentNode;
currentNode = nextNode;
}
// Update head and tail references
this.tail = this.head;
this.head = prevNode;
return this;
}
//...
}
JavaScriptclass SinglyLinkedList<T> {
//...
reverse(): SinglyLinkedList<T> {
// Reverse the linked list
let currentNode = this.head;
let prevNode = null;
let nextNode = null;
while (currentNode) {
// Traverse the list and reverse each node
nextNode = currentNode.next;
currentNode.next = prevNode;
prevNode = currentNode;
currentNode = nextNode;
}
// Update head and tail references
this.tail = this.head;
this.head = prevNode;
return this;
}
//...
}
TypeScriptclass SinglyLinkedList {
// ...
// Reverse a linked list
public function reverse(): self {
$currentNode = $this->head;
unset($this->tail);
$prevNode = null;
$nextNode = null;
while ($currentNode !== null) {
$nextNode = $currentNode->next;
$currentNode->next = $prevNode;
$prevNode = $currentNode;
$currentNode = $nextNode;
}
$this->tail = $this->head;
$this->head = $prevNode;
return $this;
}
// ...
}
PHPclass SinglyLinkedList:
# Other functionality
# Reverse a linked list
def reverse(self):
current_node = self.head
prev_node = None
next_node = None
self.tail = self.head
while current_node:
next_node = current_node.next
current_node.next = prev_node
prev_node = current_node
current_node = next_node
self.head = prev_node
return self
PythonFull Implementation Code
Here is the full implementation of Singly Linked List, with all the functionality.
// sll.js
// Singly linked list in JavaScript
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
class SinglyLinkedList {
constructor() {
this.head = null;
this.tail = null;
this.length = 0;
}
// Push item at the end of the list
push(data) {
const node = new Node(data);
// If the list is empty
// then make this node as head and tail
if (!this.head) {
this.head = node;
} else {
// set the current tail's next value to new node
this.tail.next = node;
}
// Set the tail to this new node
this.tail = node;
// Increase the length by 1
this.length++;
// Return the SinglyLinkedList
return this;
}
// Pop the last item
pop() {
// If there is no head
// then the list does not exist
if (!this.head) {
return null;
}
let current = this.head;
let newTail = current;
// Traverse through the list
// and get the second last item as newTail
while (current.next) {
newTail = current;
current = current.next;
}
// Assign the newTail to the tail
this.tail = newTail;
// Delete the next pointer of the tail
this.tail.next = null;
this.length--;
// Reset head and tail if it was the last item
if (this.length == 0) {
this.head = null;
this.tail = null;
}
// Return the popped item
return current;
}
// Traverse the list
traverse() {
let current = this.head;
while (current) {
console.log(current.data);
// Change current to the next node
current = current.next;
}
}
// Shift head
// and make the second item as head
// also return the first item
shift() {
// If there is no head then return null
if (!this.head) {
return null;
}
const currHead = this.head;
// Set the second item as head
this.head = currHead.next;
// Reduce the length by one
this.length--;
if (this.length === 0) {
this.head = null;
this.tail = null;
}
// Return the head item
return currHead;
}
// Unshift head
// Create new node and set that as head
unshift(value) {
// Create new Node from value
let newHead = new Node(value);
if (!this.head) {
this.tail = newHead;
} else {
newHead.next = this.head;
}
// Set the new node as head
this.head = newHead;
// Increase length by one
this.length++;
return this;
}
// Get node by index(sequence numbers)
// 0 based index (index starts from 0)
get(index) {
// Check if the index is valid
if (index < 0 || index >= this.length) {
return null;
}
let selectedNode = this.head;
for (let i = 1; i <= index; i++) {
selectedNode = selectedNode.next;
}
return selectedNode;
}
// Set data of a specific node at specific index
// 0 based index(index starts from 0)
set(index, data) {
let nodeAtIndex = this.get(index);
if (nodeAtIndex) {
nodeAtIndex.data = data;
return true;
}
return false;
}
}
export default SinglyLinkedList;
JavaScript// sll.ts
// Singly linked list in TypeScript
class Node<T> {
// Node class for storing data and reference to the next node
data: T;
next: Node<T> | null;
constructor(data: T) {
this.data = data;
this.next = null;
}
}
class SinglyLinkedList<T> {
// Singly Linked List class
public head: Node<T> | null;
public tail: Node<T> | null;
public length: number;
constructor() {
// Initialize head, tail, and length
this.head = null;
this.tail = null;
this.length = 0;
}
push(data: T): SinglyLinkedList<T> {
// Add data at the end of the list
const node = new Node(data);
if (!this.head) {
// If list is empty, set head and tail to new node
this.head = node;
} else {
// Otherwise, set the next of current tail to new node
this.tail!.next = node;
}
// Set new node as the tail
this.tail = node;
// Increase the length
this.length++;
return this;
}
pop(): Node<T> | null {
// Remove and return the last element from the list
if (!this.head) {
// If list is empty, return null
return null;
}
let current = this.head;
let newTail = current;
while (current.next) {
// Traverse the list to find the second last node
newTail = current;
current = current.next;
}
// Update tail and remove the last node
this.tail = newTail;
this.tail.next = null;
this.length--;
if (this.length === 0) {
// If list becomes empty, reset head and tail
this.head = null;
this.tail = null;
}
return current;
}
traverse(): void {
// Traverse the list and log the data of each node
let current = this.head;
while (current) {
console.log(current.data);
current = current.next;
}
}
shift(): Node<T> | null {
// Remove and return the first element from the list
if (!this.head) {
// If list is empty, return null
return null;
}
const currHead = this.head;
// Move head to the next node
this.head = currHead.next;
this.length--;
if (this.length === 0) {
// If list becomes empty, reset head and tail
this.head = null;
this.tail = null;
}
return currHead;
}
unshift(value: T): SinglyLinkedList<T> {
// Add data at the beginning of the list
let newHead = new Node(value);
if (!this.head) {
// If list is empty, set head and tail to new node
this.tail = newHead;
} else {
// Otherwise, set the next of new node to current head
newHead.next = this.head;
}
// Set new node as the head
this.head = newHead;
// Increase the length
this.length++;
return this;
}
get(index: number): Node<T> | null {
// Get node at a specified index
if (index < 0 || index >= this.length) {
// If index is out of range, return null
return null;
}
let selectedNode = this.head;
for (let i = 1; i <= index; i++) {
// Traverse the list to find the node at the given index
selectedNode = selectedNode!.next;
}
return selectedNode;
}
search(data: T): number | null {
// Search for the index of a specific data in the list
let current = this.head;
let index = 0;
while (current) {
// Traverse the list and check data of each node
if (current.data === data) {
// If data is found, return its index
return index;
}
current = current.next;
index++;
}
// If data is not found, return null
return null;
}
set(index: number, data: T): boolean {
// Set data of a specific node at a given index
let nodeAtIndex = this.get(index);
if (nodeAtIndex) {
// If node at given index exists, update its data
nodeAtIndex.data = data;
return true;
}
// If node at given index does not exist, return false
return false;
}
insert(index: number, data: T): boolean {
// Insert new node at a specific index
if (index < 0 || index > this.length) {
// If index is out of range, return false
return false;
}
if (index === this.length) {
// If index is at the end, use push method
this.push(data);
return true;
}
if (index === 0) {
// If index is at the beginning, use unshift method
this.unshift(data);
return true;
}
// Otherwise, insert new node at the specified index
let newNode = new Node(data);
let prevNode = this.get(index - 1);
newNode.next = prevNode!.next;
prevNode!.next = newNode;
// Increase length
this.length++;
return true;
}
remove(index: number): Node<T> | null {
// Remove node at a specific index
if (index < 0 || index >= this.length) {
// If index is out of range, return undefined
return null;
}
if (index === 0) {
// If index is at the beginning, use shift method
return this.shift();
}
if (index === this.length - 1) {
// If index is at the end, use pop method
return this.pop();
}
// Otherwise, remove node at the specified index
let prevNode = this.get(index - 1);
const removedNode = prevNode!.next;
prevNode!.next = prevNode!.next!.next;
// Decrease length
this.length--;
return removedNode;
}
reverse(): SinglyLinkedList<T> {
// Reverse the linked list
let currentNode = this.head;
let prevNode = null;
let nextNode = null;
while (currentNode) {
// Traverse the list and reverse each node
nextNode = currentNode.next;
currentNode.next = prevNode;
prevNode = currentNode;
currentNode = nextNode;
}
// Update head and tail references
this.tail = this.head;
this.head = prevNode;
return this;
}
}
export default SinglyLinkedList;
TypeScript NOTE
The following implementation is not part Linked List implementation. This is just for iterating the list easily.
It is included here as the iterator implementation using the PHP Iterator interface makes it easy to iterate over the items of the list.
use Iterator;
class SinglyLinkedList implements Iterator{
// For Iterator implementation
// Not specifically related to the linked list
private ?Node $currentNode;
private int $currentKey = 0;
// ... Other implementation code
// Part of Iterator interface implementation
// Get current node
public function current(): string {
return $this->currentNode->data;
}
// Part of Iterator interface implementation
// Get current key
public function key(): int {
return $this->currentKey;
}
// Part of Iterator interface implementation
// Move to the next item
public function next(): void {
$this->currentNode = $this->currentNode->next;
$this->currentKey++;
}
// Part of Iterator interface implementation
// Rewind the iterator
public function rewind(): void {
$this->currentKey = 0;
$this->currentNode = $this->head;
}
// Part of Iterator interface implementation
// Check is valid
public function valid(): bool {
return $this->currentNode !== null;
}
}
PHPHere is the full PHP code-
<?php
declare(strict_types=1);
use Iterator;
class Node {
public ?Node $next = null;
public function __construct(public string $data) {
}
}
class SinglyLinkedList implements Iterator{
public ?Node $head = null;
public ?Node $tail = null;
public int $length = 0;
// For Iterator implementation
// Not specifically related to the linked list
private ?Node $currentNode;
private int $currentKey = 0;
public function __construct() {
}
// Push node to the end of the list
public function push(string $data): bool {
$node = new Node($data);
// If the list is empty
// then make this node as head and tail
if ($this->head === null) {
$this->head = $node;
} else {
// set the current tail's next value to new node
$this->tail->next = $node;
}
// Set the tail to this new node
$this->tail = $node;
// Increase the length by 1
$this->length++;
return true;
}
// Pop the last item
public function pop(): ?Node {
// If there is no head
// then the list does not exist
if ($this->head === null) {
return null;
}
$current = $this->head;
$newTail = $current;
// Traverse through the list
// and get the second last item as newTail
while ($current->next !== null) {
$newTail = $current;
$current = $current->next;
}
// Assign the newTail to the tail
$this->tail = $newTail;
// Delete the next pointer of the tail
$this->tail->next = null;
$this->length--;
// Reset head and tail if it was the last item
if ($this->length == 0) {
$this->head = null;
$this->tail = null;
}
// Return the popped item
return $current;
}
// Traverse the list
public function traverse(): void {
$current = $this->head;
while ($current !== null) {
echo $current->data . PHP_EOL;
// Change current to the next node
$current = $current->next;
}
}
// Shift head
// and make the second item as head
// also return the first item
public function shift(): ?Node {
// If there is no head then return null
if ($this->head === null) {
return null;
}
$oldHead = $this->head;
// Set the second item as head
$this->head = $oldHead->next;
// Reduce the length by one
$this->length--;
if ($this->length === 0) {
$this->head = null;
$this->tail = null;
}
// Return the head item
return $oldHead;
}
// Unshift head
// Create new node and set that as head
public function unshift($value): bool {
// Create new Node from value
$newHead = new Node($value);
if ($this->head === null) {
$this->tail = $newHead;
} else {
$newHead->next = $this->head;
}
// Set the new node as head
$this->head = $newHead;
// Increase length by one
$this->length++;
return true;
}
// Get node by index(sequence numbers)
// 0 based index (index starts from 0)
public function get(int $index): ?Node {
// Check if the index is valid
if ($index < 0 || $index >= $this->length) {
return null;
}
$selectedNode = $this->head;
for ($i = 1; $i <= $index; $i++) {
$selectedNode = $selectedNode->next;
}
return $selectedNode;
}
// Set data of a specific node at specific index
// 0 based index(index starts from 0)
public function set(int $index, string $data): bool {
$nodeAtIndex = $this->get($index);
if ($nodeAtIndex) {
$nodeAtIndex->data = $data;
return true;
}
return false;
}
// Search the list for specific data
public function search(string $data): ?int {
$current = $this->head;
$index = 0;
while ($current) {
if ($current->data === $data) {
return $index;
}
$current = $current->next;
$index++;
}
<