mirror of
https://github.com/TheAlgorithms/JavaScript.git
synced 2025-07-05 08:16:50 +08:00
Refactored code to improve performance of some methods (#1284)
* refactored code to improve perfomance * added 'check tail' test * corrected styling and spelling mistake
This commit is contained in:
@ -1,10 +1,10 @@
|
|||||||
/* SinglyLinkedList!!
|
/* SinglyLinkedList!!
|
||||||
* A linked list is similar to an array, it holds a list of values.
|
* A linked list is similar to an array, it holds a list of values.
|
||||||
* However, links in a linked list do not have indexes. With
|
* However, links in a linked list do not have indexes. With
|
||||||
* a linked list you do not need to predetermine its size as
|
* a linked list you do not need to predetermine its size as
|
||||||
* it grows and shrinks as it is edited. This is an example of
|
* it grows and shrinks as it is edited. This is an example of
|
||||||
* a singly linked list.
|
* a singly linked list.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Methods - size, head, addLast, addFirst, addAt, removeFirst, removeLast, remove, removeAt, indexOf, isEmpty, elementAt, findMiddle, get, clean, rotateListRight
|
// Methods - size, head, addLast, addFirst, addAt, removeFirst, removeLast, remove, removeAt, indexOf, isEmpty, elementAt, findMiddle, get, clean, rotateListRight
|
||||||
|
|
||||||
@ -18,6 +18,7 @@ class Node {
|
|||||||
class LinkedList {
|
class LinkedList {
|
||||||
constructor (listOfValues) {
|
constructor (listOfValues) {
|
||||||
this.headNode = null
|
this.headNode = null
|
||||||
|
this.tailNode = null
|
||||||
this.length = 0
|
this.length = 0
|
||||||
|
|
||||||
if (listOfValues instanceof Array) {
|
if (listOfValues instanceof Array) {
|
||||||
@ -42,6 +43,11 @@ class LinkedList {
|
|||||||
return this.headNode?.data || null
|
return this.headNode?.data || null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the tail
|
||||||
|
tail () {
|
||||||
|
return this.tailNode?.data || null
|
||||||
|
}
|
||||||
|
|
||||||
// Return if the list is empty
|
// Return if the list is empty
|
||||||
isEmpty () {
|
isEmpty () {
|
||||||
return this.length === 0
|
return this.length === 0
|
||||||
@ -53,16 +59,10 @@ class LinkedList {
|
|||||||
if (this.headNode === null) {
|
if (this.headNode === null) {
|
||||||
return this.addFirst(element)
|
return this.addFirst(element)
|
||||||
}
|
}
|
||||||
let { currentNode } = this.initiateNodeAndIndex()
|
|
||||||
|
|
||||||
// Loop till there is a node present in the list
|
|
||||||
while (currentNode.next) {
|
|
||||||
currentNode = currentNode.next
|
|
||||||
}
|
|
||||||
|
|
||||||
const node = new Node(element)
|
const node = new Node(element)
|
||||||
// Adding node at the end of the list and increase the length
|
// Adding node at the end of the list and increase the length
|
||||||
currentNode.next = node
|
this.tailNode.next = node
|
||||||
|
this.tailNode = node
|
||||||
this.length++
|
this.length++
|
||||||
return this.size()
|
return this.size()
|
||||||
}
|
}
|
||||||
@ -70,6 +70,11 @@ class LinkedList {
|
|||||||
// add a node at first it to linklist
|
// add a node at first it to linklist
|
||||||
addFirst (element) {
|
addFirst (element) {
|
||||||
const node = new Node(element)
|
const node = new Node(element)
|
||||||
|
// Check if its the first element
|
||||||
|
if (this.headNode === null) {
|
||||||
|
this.tailNode = node
|
||||||
|
}
|
||||||
|
// Adding node at the start of the list and increase the length
|
||||||
node.next = this.headNode
|
node.next = this.headNode
|
||||||
this.headNode = node
|
this.headNode = node
|
||||||
this.length++
|
this.length++
|
||||||
@ -78,10 +83,17 @@ class LinkedList {
|
|||||||
|
|
||||||
// remove the first from the linklist
|
// remove the first from the linklist
|
||||||
removeFirst () {
|
removeFirst () {
|
||||||
|
// Check if head is null
|
||||||
|
if (this.headNode === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
// Removing node at the start of the list and decrease the length
|
||||||
const removedNode = this.headNode
|
const removedNode = this.headNode
|
||||||
if (this.length > 0) {
|
this.headNode = this.headNode.next
|
||||||
this.headNode = this.headNode.next
|
this.length--
|
||||||
this.length--
|
// Check if the list is empty
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
this.tailNode = null
|
||||||
}
|
}
|
||||||
return removedNode?.data
|
return removedNode?.data
|
||||||
}
|
}
|
||||||
@ -89,16 +101,18 @@ class LinkedList {
|
|||||||
// remove the last from the linklist
|
// remove the last from the linklist
|
||||||
removeLast () {
|
removeLast () {
|
||||||
if (this.isEmpty()) return null
|
if (this.isEmpty()) return null
|
||||||
|
// Check if there is only one element
|
||||||
if (this.length === 1) {
|
if (this.length === 1) {
|
||||||
return this.removeFirst()
|
return this.removeFirst()
|
||||||
}
|
}
|
||||||
let { currentIndex, currentNode } = this.initiateNodeAndIndex()
|
// Removing node at the end of the list and decrease the length
|
||||||
while (currentIndex !== this.length - 2) {
|
const removedNode = this.tailNode
|
||||||
currentIndex++
|
let { currentNode } = this.initiateNodeAndIndex()
|
||||||
|
while (currentNode.next.next) {
|
||||||
currentNode = currentNode.next
|
currentNode = currentNode.next
|
||||||
}
|
}
|
||||||
const removedNode = currentNode.next
|
|
||||||
currentNode.next = null
|
currentNode.next = null
|
||||||
|
this.tailNode = currentNode
|
||||||
this.length--
|
this.length--
|
||||||
return removedNode.data
|
return removedNode.data
|
||||||
}
|
}
|
||||||
@ -112,13 +126,17 @@ class LinkedList {
|
|||||||
if (currentNode.data === element) {
|
if (currentNode.data === element) {
|
||||||
return this.removeFirst()
|
return this.removeFirst()
|
||||||
}
|
}
|
||||||
|
// Check if the tail node is the element to remove
|
||||||
|
if (this.tailNode.data === element) {
|
||||||
|
return this.removeLast()
|
||||||
|
}
|
||||||
// Check which node is the node to remove
|
// Check which node is the node to remove
|
||||||
while (currentNode?.next) {
|
while (currentNode.next) {
|
||||||
if (currentNode.next.data === element) {
|
if (currentNode.next.data === element) {
|
||||||
removedNode = currentNode.next
|
removedNode = currentNode.next
|
||||||
currentNode.next = currentNode.next.next
|
currentNode.next = currentNode.next.next
|
||||||
this.length--
|
this.length--
|
||||||
break
|
return removedNode.data
|
||||||
}
|
}
|
||||||
currentNode = currentNode.next
|
currentNode = currentNode.next
|
||||||
}
|
}
|
||||||
@ -127,10 +145,9 @@ class LinkedList {
|
|||||||
|
|
||||||
// Returns the index of the element passed as param otherwise -1
|
// Returns the index of the element passed as param otherwise -1
|
||||||
indexOf (element) {
|
indexOf (element) {
|
||||||
let { currentIndex, currentNode } = this.initiateNodeAndIndex()
|
if (this.isEmpty()) return -1
|
||||||
|
let { currentNode, currentIndex } = this.initiateNodeAndIndex()
|
||||||
while (currentNode) {
|
while (currentNode) {
|
||||||
// Checking if the node is the element we are searching for
|
|
||||||
if (currentNode.data === element) {
|
if (currentNode.data === element) {
|
||||||
return currentIndex
|
return currentIndex
|
||||||
}
|
}
|
||||||
@ -185,7 +202,7 @@ class LinkedList {
|
|||||||
throw new RangeError('Out of Range index')
|
throw new RangeError('Out of Range index')
|
||||||
}
|
}
|
||||||
if (index === 0) return this.removeFirst()
|
if (index === 0) return this.removeFirst()
|
||||||
if (index === this.length) return this.removeLast()
|
if (index === this.length - 1) return this.removeLast()
|
||||||
|
|
||||||
let { currentIndex, currentNode } = this.initiateNodeAndIndex()
|
let { currentIndex, currentNode } = this.initiateNodeAndIndex()
|
||||||
while (currentIndex !== index - 1) {
|
while (currentIndex !== index - 1) {
|
||||||
@ -194,7 +211,6 @@ class LinkedList {
|
|||||||
}
|
}
|
||||||
const removedNode = currentNode.next
|
const removedNode = currentNode.next
|
||||||
currentNode.next = currentNode.next.next
|
currentNode.next = currentNode.next.next
|
||||||
// Decrementing the length
|
|
||||||
this.length--
|
this.length--
|
||||||
return removedNode.data
|
return removedNode.data
|
||||||
}
|
}
|
||||||
@ -215,6 +231,7 @@ class LinkedList {
|
|||||||
// make the linkedList Empty
|
// make the linkedList Empty
|
||||||
clean () {
|
clean () {
|
||||||
this.headNode = null
|
this.headNode = null
|
||||||
|
this.tailNode = null
|
||||||
this.length = 0
|
this.length = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,34 +243,28 @@ class LinkedList {
|
|||||||
list.push(currentNode.data)
|
list.push(currentNode.data)
|
||||||
currentNode = currentNode.next
|
currentNode = currentNode.next
|
||||||
}
|
}
|
||||||
|
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method for Rotating a List to the right by k places
|
// Method for Rotating a List to the right by k places
|
||||||
rotateListRight (k) {
|
rotateListRight (k) {
|
||||||
let i = 0
|
if (!this.headNode) return
|
||||||
let current = this.headNode
|
let current = this.headNode
|
||||||
while (current) {
|
let tail = this.tailNode
|
||||||
i++
|
let count = 1
|
||||||
|
while (current.next) {
|
||||||
|
count++
|
||||||
current = current.next
|
current = current.next
|
||||||
}
|
}
|
||||||
k %= i
|
current.next = this.headNode
|
||||||
current = this.headNode
|
tail = current
|
||||||
let prev = null
|
k %= count
|
||||||
while (k--) {
|
while (count - k > 0) {
|
||||||
if (!current || !current.next) {
|
tail = tail.next
|
||||||
return current
|
count--
|
||||||
} else {
|
|
||||||
while (current.next) {
|
|
||||||
prev = current
|
|
||||||
current = current.next
|
|
||||||
}
|
|
||||||
prev.next = current.next
|
|
||||||
current.next = this.headNode
|
|
||||||
this.headNode = current
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.headNode = tail.next
|
||||||
|
tail.next = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method to iterate over the LinkedList
|
// Method to iterate over the LinkedList
|
||||||
@ -286,6 +297,7 @@ class LinkedList {
|
|||||||
prev = head
|
prev = head
|
||||||
head = next
|
head = next
|
||||||
}
|
}
|
||||||
|
this.tailNode = this.headNode
|
||||||
this.headNode = prev
|
this.headNode = prev
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -150,6 +150,20 @@ describe('SinglyLinkedList', () => {
|
|||||||
expect(list.head()).toBe(30)
|
expect(list.head()).toBe(30)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Check tail', () => {
|
||||||
|
const list = new LinkedList()
|
||||||
|
expect(list.tail()).toBe(null)
|
||||||
|
|
||||||
|
list.addLast(10)
|
||||||
|
expect(list.tail()).toBe(10)
|
||||||
|
|
||||||
|
list.addLast(20)
|
||||||
|
expect(list.tail()).toBe(20)
|
||||||
|
|
||||||
|
list.addFirst(30)
|
||||||
|
expect(list.tail()).toBe(20)
|
||||||
|
})
|
||||||
|
|
||||||
it('Check size', () => {
|
it('Check size', () => {
|
||||||
const list = new LinkedList()
|
const list = new LinkedList()
|
||||||
expect(list.size()).toBe(0)
|
expect(list.size()).toBe(0)
|
||||||
|
Reference in New Issue
Block a user