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:
Teddy Mwai
2023-02-08 15:46:57 +03:00
committed by GitHub
parent c252df5d10
commit c40e4cf4d4
2 changed files with 73 additions and 47 deletions

View File

@ -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
current = current.next
}
k %= i
current = this.headNode
let prev = null
while (k--) {
if (!current || !current.next) {
return current
} else {
while (current.next) { while (current.next) {
prev = current count++
current = current.next current = current.next
} }
prev.next = current.next
current.next = this.headNode current.next = this.headNode
this.headNode = current tail = current
} k %= count
while (count - k > 0) {
tail = tail.next
count--
} }
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
}; };
} }

View File

@ -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)