mirror of
https://github.com/TheAlgorithms/JavaScript.git
synced 2025-07-06 17:50:39 +08:00
feat: Test running overhaul, switch to Prettier & reformat everything (#1407)
* chore: Switch to Node 20 + Vitest * chore: migrate to vitest mock functions * chore: code style (switch to prettier) * test: re-enable long-running test Seems the switch to Node 20 and Vitest has vastly improved the code's and / or the test's runtime! see #1193 * chore: code style * chore: fix failing tests * Updated Documentation in README.md * Update contribution guidelines to state usage of Prettier * fix: set prettier printWidth back to 80 * chore: apply updated code style automatically * fix: set prettier line endings to lf again * chore: apply updated code style automatically --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
This commit is contained in:
@ -9,19 +9,38 @@
|
||||
* @complexity: O(log(n)) (worst case)
|
||||
* @flow
|
||||
*/
|
||||
const findMaxPointIndex = (array, rangeStartIndex, rangeEndIndex, originalLength) => {
|
||||
const findMaxPointIndex = (
|
||||
array,
|
||||
rangeStartIndex,
|
||||
rangeEndIndex,
|
||||
originalLength
|
||||
) => {
|
||||
// find index range middle point
|
||||
const middleIndex = rangeStartIndex + parseInt((rangeEndIndex - rangeStartIndex) / 2)
|
||||
const middleIndex =
|
||||
rangeStartIndex + parseInt((rangeEndIndex - rangeStartIndex) / 2)
|
||||
|
||||
// handle array bounds
|
||||
if ((middleIndex === 0 || array[middleIndex - 1] <= array[middleIndex]) &&
|
||||
(middleIndex === originalLength - 1 || array[middleIndex + 1] <= array[middleIndex])) {
|
||||
if (
|
||||
(middleIndex === 0 || array[middleIndex - 1] <= array[middleIndex]) &&
|
||||
(middleIndex === originalLength - 1 ||
|
||||
array[middleIndex + 1] <= array[middleIndex])
|
||||
) {
|
||||
return middleIndex
|
||||
} else if (middleIndex > 0 && array[middleIndex - 1] > array[middleIndex]) {
|
||||
return findMaxPointIndex(array, rangeStartIndex, (middleIndex - 1), originalLength)
|
||||
return findMaxPointIndex(
|
||||
array,
|
||||
rangeStartIndex,
|
||||
middleIndex - 1,
|
||||
originalLength
|
||||
)
|
||||
} else {
|
||||
// regular local max
|
||||
return findMaxPointIndex(array, (middleIndex + 1), rangeEndIndex, originalLength)
|
||||
return findMaxPointIndex(
|
||||
array,
|
||||
middleIndex + 1,
|
||||
rangeEndIndex,
|
||||
originalLength
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,13 @@ const CountLocalMaximumPoints = (array, startIndex, endIndex) => {
|
||||
|
||||
// handle the two halves
|
||||
const middleIndex = parseInt((startIndex + endIndex) / 2)
|
||||
return CountLocalMaximumPoints(array, startIndex, middleIndex) +
|
||||
return (
|
||||
CountLocalMaximumPoints(array, startIndex, middleIndex) +
|
||||
CountLocalMaximumPoints(array, middleIndex + 1, endIndex)
|
||||
)
|
||||
}
|
||||
|
||||
const NumberOfLocalMaximumPoints = (A) => CountLocalMaximumPoints(A, 0, A.length - 1)
|
||||
const NumberOfLocalMaximumPoints = (A) =>
|
||||
CountLocalMaximumPoints(A, 0, A.length - 1)
|
||||
|
||||
export { NumberOfLocalMaximumPoints }
|
||||
|
@ -11,7 +11,8 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
function QuickSelect (items, kth) { // eslint-disable-line no-unused-vars
|
||||
function QuickSelect(items, kth) {
|
||||
// eslint-disable-line no-unused-vars
|
||||
if (kth < 1 || kth > items.length) {
|
||||
throw new RangeError('Index Out of Bound')
|
||||
}
|
||||
@ -19,7 +20,7 @@ function QuickSelect (items, kth) { // eslint-disable-line no-unused-vars
|
||||
return RandomizedSelect(items, 0, items.length - 1, kth)
|
||||
}
|
||||
|
||||
function RandomizedSelect (items, left, right, i) {
|
||||
function RandomizedSelect(items, left, right, i) {
|
||||
if (left === right) return items[left]
|
||||
|
||||
const pivotIndex = RandomizedPartition(items, left, right)
|
||||
@ -31,13 +32,13 @@ function RandomizedSelect (items, left, right, i) {
|
||||
return RandomizedSelect(items, pivotIndex + 1, right, i - k)
|
||||
}
|
||||
|
||||
function RandomizedPartition (items, left, right) {
|
||||
function RandomizedPartition(items, left, right) {
|
||||
const rand = getRandomInt(left, right)
|
||||
Swap(items, rand, right)
|
||||
return Partition(items, left, right)
|
||||
}
|
||||
|
||||
function Partition (items, left, right) {
|
||||
function Partition(items, left, right) {
|
||||
const x = items[right]
|
||||
let pivotIndex = left - 1
|
||||
|
||||
@ -53,12 +54,12 @@ function Partition (items, left, right) {
|
||||
return pivotIndex + 1
|
||||
}
|
||||
|
||||
function getRandomInt (min, max) {
|
||||
function getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min
|
||||
}
|
||||
|
||||
function Swap (arr, x, y) {
|
||||
[arr[x], arr[y]] = [arr[y], arr[x]]
|
||||
function Swap(arr, x, y) {
|
||||
;[arr[x], arr[y]] = [arr[y], arr[x]]
|
||||
}
|
||||
|
||||
export { QuickSelect }
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { Reverse } from '../Reverse.js'
|
||||
import each from 'jest-each'
|
||||
|
||||
describe('reverse elements in an array', () => {
|
||||
each`
|
||||
array | expected
|
||||
${[]} | ${[]}
|
||||
${[1]} | ${[1]}
|
||||
${[1, 2, 3, 4]} | ${[4, 3, 2, 1]}
|
||||
`.test('returns $expected when given $array', ({ array, expected }) => {
|
||||
expect(Reverse(array)).toEqual(expected)
|
||||
})
|
||||
it.each([
|
||||
[[], []],
|
||||
[[1], [1]],
|
||||
[
|
||||
[1, 2, 3, 4],
|
||||
[4, 3, 2, 1]
|
||||
]
|
||||
])('returns %j when given %j', (array, expected) => {
|
||||
expect(Reverse(array)).toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
@ -1,24 +1,24 @@
|
||||
class Graph {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.adjacencyMap = {}
|
||||
}
|
||||
|
||||
addVertex (vertex) {
|
||||
addVertex(vertex) {
|
||||
this.adjacencyMap[vertex] = []
|
||||
}
|
||||
|
||||
containsVertex (vertex) {
|
||||
return typeof (this.adjacencyMap[vertex]) !== 'undefined'
|
||||
containsVertex(vertex) {
|
||||
return typeof this.adjacencyMap[vertex] !== 'undefined'
|
||||
}
|
||||
|
||||
addEdge (vertex1, vertex2) {
|
||||
addEdge(vertex1, vertex2) {
|
||||
if (this.containsVertex(vertex1) && this.containsVertex(vertex2)) {
|
||||
this.adjacencyMap[vertex1].push(vertex2)
|
||||
this.adjacencyMap[vertex2].push(vertex1)
|
||||
}
|
||||
}
|
||||
|
||||
printGraph (output = value => console.log(value)) {
|
||||
printGraph(output = (value) => console.log(value)) {
|
||||
const keys = Object.keys(this.adjacencyMap)
|
||||
for (const i of keys) {
|
||||
const values = this.adjacencyMap[i]
|
||||
@ -34,13 +34,14 @@ class Graph {
|
||||
* Prints the Breadth first traversal of the graph from source.
|
||||
* @param {number} source The source vertex to start BFS.
|
||||
*/
|
||||
bfs (source, output = value => console.log(value)) {
|
||||
bfs(source, output = (value) => console.log(value)) {
|
||||
const queue = [[source, 0]] // level of source is 0
|
||||
const visited = new Set()
|
||||
|
||||
while (queue.length) {
|
||||
const [node, level] = queue.shift() // remove the front of the queue
|
||||
if (visited.has(node)) { // visited
|
||||
if (visited.has(node)) {
|
||||
// visited
|
||||
continue
|
||||
}
|
||||
|
||||
@ -56,8 +57,9 @@ class Graph {
|
||||
* Prints the Depth first traversal of the graph from source.
|
||||
* @param {number} source The source vertex to start DFS.
|
||||
*/
|
||||
dfs (source, visited = new Set(), output = value => console.log(value)) {
|
||||
if (visited.has(source)) { // visited
|
||||
dfs(source, visited = new Set(), output = (value) => console.log(value)) {
|
||||
if (visited.has(source)) {
|
||||
// visited
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
class Graph {
|
||||
// defining vertex array and
|
||||
// adjacent list
|
||||
constructor (noOfVertices) {
|
||||
constructor(noOfVertices) {
|
||||
this.noOfVertices = noOfVertices
|
||||
this.AdjList = new Map()
|
||||
}
|
||||
@ -17,7 +17,7 @@ class Graph {
|
||||
// dfs(v)
|
||||
|
||||
// add vertex to the graph
|
||||
addVertex (v) {
|
||||
addVertex(v) {
|
||||
// initialize the adjacent list with a
|
||||
// null array
|
||||
|
||||
@ -25,7 +25,7 @@ class Graph {
|
||||
}
|
||||
|
||||
// add edge to the graph
|
||||
addEdge (v, w) {
|
||||
addEdge(v, w) {
|
||||
// get the list for vertex v and put the
|
||||
// vertex w denoting edge between v and w
|
||||
this.AdjList.get(v).push(w)
|
||||
@ -36,7 +36,7 @@ class Graph {
|
||||
}
|
||||
|
||||
// Prints the vertex and adjacency list
|
||||
printGraph (output = value => console.log(value)) {
|
||||
printGraph(output = (value) => console.log(value)) {
|
||||
// get all the vertices
|
||||
const getKeys = this.AdjList.keys()
|
||||
|
||||
|
@ -1,18 +1,18 @@
|
||||
class Graph {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.adjacencyObject = {}
|
||||
}
|
||||
|
||||
addVertex (vertex) {
|
||||
addVertex(vertex) {
|
||||
if (!this.adjacencyObject[vertex]) this.adjacencyObject[vertex] = []
|
||||
}
|
||||
|
||||
addEdge (vertex1, vertex2) {
|
||||
addEdge(vertex1, vertex2) {
|
||||
this.adjacencyObject[vertex1].push(vertex2)
|
||||
this.adjacencyObject[vertex2].push(vertex1)
|
||||
}
|
||||
|
||||
removeEdge (vertex1, vertex2) {
|
||||
removeEdge(vertex1, vertex2) {
|
||||
this.adjacencyObject[vertex1] = this.adjacencyObject[vertex1].filter(
|
||||
(v) => v !== vertex2
|
||||
)
|
||||
@ -21,7 +21,7 @@ class Graph {
|
||||
)
|
||||
}
|
||||
|
||||
removeVertex (vertex) {
|
||||
removeVertex(vertex) {
|
||||
while (this.adjacencyObject[vertex].length) {
|
||||
const adjacentVertex = this.adjacencyObject[vertex].pop()
|
||||
this.removeEdge(vertex, adjacentVertex)
|
||||
@ -31,14 +31,14 @@ class Graph {
|
||||
/**
|
||||
* Return DFS (Depth First Search) List Using Recursive Method
|
||||
*/
|
||||
DFS (start) {
|
||||
DFS(start) {
|
||||
if (!start) return null
|
||||
|
||||
const result = []
|
||||
const visited = {}
|
||||
const adjacencyObject = this.adjacencyObject
|
||||
|
||||
function dfs (vertex) {
|
||||
function dfs(vertex) {
|
||||
if (!vertex) return null
|
||||
visited[vertex] = true
|
||||
result.push(vertex)
|
||||
@ -56,7 +56,7 @@ class Graph {
|
||||
/**
|
||||
* Return DFS(Depth First Search) List Using Iteration
|
||||
*/
|
||||
DFSIterative (start) {
|
||||
DFSIterative(start) {
|
||||
if (!start) return null
|
||||
|
||||
const stack = [start]
|
||||
@ -80,7 +80,7 @@ class Graph {
|
||||
return result
|
||||
}
|
||||
|
||||
BFS (start) {
|
||||
BFS(start) {
|
||||
if (!start) return null
|
||||
|
||||
const queue = [start]
|
||||
|
@ -18,7 +18,7 @@ describe('Test Graph2', () => {
|
||||
graph.addEdge('C', 'F')
|
||||
|
||||
it('Check adjacency lists', () => {
|
||||
const mockFn = jest.fn()
|
||||
const mockFn = vi.fn()
|
||||
graph.printGraph(mockFn)
|
||||
|
||||
// Expect one call per vertex
|
||||
|
@ -19,12 +19,12 @@
|
||||
*/
|
||||
|
||||
// Priority Queue Helper functions
|
||||
const getParentPosition = position => Math.floor((position - 1) / 2)
|
||||
const getChildrenPositions = position => [2 * position + 1, 2 * position + 2]
|
||||
const getParentPosition = (position) => Math.floor((position - 1) / 2)
|
||||
const getChildrenPositions = (position) => [2 * position + 1, 2 * position + 2]
|
||||
|
||||
class KeyPriorityQueue {
|
||||
// Priority Queue class using Minimum Binary Heap
|
||||
constructor () {
|
||||
constructor() {
|
||||
this._heap = []
|
||||
this.priorities = new Map()
|
||||
}
|
||||
@ -33,7 +33,7 @@ class KeyPriorityQueue {
|
||||
* Checks if the heap is empty
|
||||
* @returns boolean
|
||||
*/
|
||||
isEmpty () {
|
||||
isEmpty() {
|
||||
return this._heap.length === 0
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ class KeyPriorityQueue {
|
||||
* @param {*} key
|
||||
* @param {number} priority
|
||||
*/
|
||||
push (key, priority) {
|
||||
push(key, priority) {
|
||||
this._heap.push(key)
|
||||
this.priorities.set(key, priority)
|
||||
this._shiftUp(this._heap.length - 1)
|
||||
@ -52,7 +52,7 @@ class KeyPriorityQueue {
|
||||
* Removes the element with least priority
|
||||
* @returns the key of the element with least priority
|
||||
*/
|
||||
pop () {
|
||||
pop() {
|
||||
this._swap(0, this._heap.length - 1)
|
||||
const key = this._heap.pop()
|
||||
this.priorities.delete(key)
|
||||
@ -65,7 +65,7 @@ class KeyPriorityQueue {
|
||||
* @param {*} key
|
||||
* @returns boolean
|
||||
*/
|
||||
contains (key) {
|
||||
contains(key) {
|
||||
return this.priorities.has(key)
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ class KeyPriorityQueue {
|
||||
* @param {*} key the element to change
|
||||
* @param {number} priority new priority of the element
|
||||
*/
|
||||
update (key, priority) {
|
||||
update(key, priority) {
|
||||
const currPos = this._heap.indexOf(key)
|
||||
// if the key does not exist yet, add it
|
||||
if (currPos === -1) return this.push(key, priority)
|
||||
@ -95,13 +95,14 @@ class KeyPriorityQueue {
|
||||
}
|
||||
}
|
||||
|
||||
_getPriorityOrInfinite (position) {
|
||||
_getPriorityOrInfinite(position) {
|
||||
// Helper function, returns priority of the node, or Infinite if no node corresponds to this position
|
||||
if (position >= 0 && position < this._heap.length) return this.priorities.get(this._heap[position])
|
||||
if (position >= 0 && position < this._heap.length)
|
||||
return this.priorities.get(this._heap[position])
|
||||
else return Infinity
|
||||
}
|
||||
|
||||
_shiftUp (position) {
|
||||
_shiftUp(position) {
|
||||
// Helper function to shift up a node to proper position (equivalent to bubbleUp)
|
||||
let currPos = position
|
||||
let parentPos = getParentPosition(currPos)
|
||||
@ -117,7 +118,7 @@ class KeyPriorityQueue {
|
||||
}
|
||||
}
|
||||
|
||||
_shiftDown (position) {
|
||||
_shiftDown(position) {
|
||||
// Helper function to shift down a node to proper position (equivalent to bubbleDown)
|
||||
let currPos = position
|
||||
let [child1Pos, child2Pos] = getChildrenPositions(currPos)
|
||||
@ -137,16 +138,19 @@ class KeyPriorityQueue {
|
||||
this._swap(child2Pos, currPos)
|
||||
currPos = child2Pos
|
||||
}
|
||||
[child1Pos, child2Pos] = getChildrenPositions(currPos)
|
||||
;[child1Pos, child2Pos] = getChildrenPositions(currPos)
|
||||
child1Priority = this._getPriorityOrInfinite(child1Pos)
|
||||
child2Priority = this._getPriorityOrInfinite(child2Pos)
|
||||
currPriority = this._getPriorityOrInfinite(currPos)
|
||||
}
|
||||
}
|
||||
|
||||
_swap (position1, position2) {
|
||||
_swap(position1, position2) {
|
||||
// Helper function to swap 2 nodes
|
||||
[this._heap[position1], this._heap[position2]] = [this._heap[position2], this._heap[position1]]
|
||||
;[this._heap[position1], this._heap[position2]] = [
|
||||
this._heap[position2],
|
||||
this._heap[position1]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,25 +4,25 @@
|
||||
*/
|
||||
|
||||
class BinaryHeap {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.heap = []
|
||||
}
|
||||
|
||||
insert (value) {
|
||||
insert(value) {
|
||||
this.heap.push(value)
|
||||
this.heapify()
|
||||
}
|
||||
|
||||
size () {
|
||||
size() {
|
||||
return this.heap.length
|
||||
}
|
||||
|
||||
empty () {
|
||||
empty() {
|
||||
return this.size() === 0
|
||||
}
|
||||
|
||||
// using iterative approach to reorder the heap after insertion
|
||||
heapify () {
|
||||
heapify() {
|
||||
let index = this.size() - 1
|
||||
|
||||
while (index > 0) {
|
||||
@ -38,7 +38,7 @@ class BinaryHeap {
|
||||
}
|
||||
|
||||
// Extracting the maximum element from the Heap
|
||||
extractMax () {
|
||||
extractMax() {
|
||||
const max = this.heap[0]
|
||||
const tmp = this.heap.pop()
|
||||
if (!this.empty()) {
|
||||
@ -49,7 +49,7 @@ class BinaryHeap {
|
||||
}
|
||||
|
||||
// To restore the balance of the heap after extraction.
|
||||
sinkDown (index) {
|
||||
sinkDown(index) {
|
||||
const left = 2 * index + 1
|
||||
const right = 2 * index + 2
|
||||
let largest = index
|
||||
|
@ -19,15 +19,15 @@
|
||||
*/
|
||||
|
||||
class MinHeap {
|
||||
constructor (array) {
|
||||
constructor(array) {
|
||||
this.heap = this.initializeHeap(array)
|
||||
}
|
||||
|
||||
/**
|
||||
* startingParent represents the parent of the last index (=== array.length-1)
|
||||
* and iterates towards 0 with all index values below sorted to meet heap conditions
|
||||
*/
|
||||
initializeHeap (array) {
|
||||
*/
|
||||
initializeHeap(array) {
|
||||
const startingParent = Math.floor((array.length - 2) / 2)
|
||||
|
||||
for (let currIdx = startingParent; currIdx >= 0; currIdx--) {
|
||||
@ -52,15 +52,16 @@ class MinHeap {
|
||||
* update currIdx and recalculate the new childOneIdx to check heap conditions again.
|
||||
*
|
||||
* if there is no swap, it means the children indices and the parent index satisfy heap conditions and can exit the function.
|
||||
*/
|
||||
sinkDown (currIdx, endIdx, heap) {
|
||||
*/
|
||||
sinkDown(currIdx, endIdx, heap) {
|
||||
let childOneIdx = currIdx * 2 + 1
|
||||
|
||||
while (childOneIdx <= endIdx) {
|
||||
const childTwoIdx = childOneIdx + 1 <= endIdx ? childOneIdx + 1 : -1
|
||||
const swapIdx = childTwoIdx !== -1 && heap[childTwoIdx] < heap[childOneIdx]
|
||||
? childTwoIdx
|
||||
: childOneIdx
|
||||
const swapIdx =
|
||||
childTwoIdx !== -1 && heap[childTwoIdx] < heap[childOneIdx]
|
||||
? childTwoIdx
|
||||
: childOneIdx
|
||||
|
||||
if (heap[swapIdx] < heap[currIdx]) {
|
||||
this.swap(currIdx, swapIdx, heap)
|
||||
@ -79,8 +80,8 @@ class MinHeap {
|
||||
* update currIdx and recalculate the new parentIdx to check heap condition again.
|
||||
*
|
||||
* iteration does not end while a valid currIdx has a value smaller than its parentIdx's value
|
||||
*/
|
||||
bubbleUp (currIdx) {
|
||||
*/
|
||||
bubbleUp(currIdx) {
|
||||
let parentIdx = Math.floor((currIdx - 1) / 2)
|
||||
|
||||
while (currIdx > 0 && this.heap[currIdx] < this.heap[parentIdx]) {
|
||||
@ -90,7 +91,7 @@ class MinHeap {
|
||||
}
|
||||
}
|
||||
|
||||
peek () {
|
||||
peek() {
|
||||
return this.heap[0]
|
||||
}
|
||||
|
||||
@ -101,8 +102,8 @@ class MinHeap {
|
||||
* the resulting min heap value now resides at heap[heap.length-1] which is popped and later returned.
|
||||
*
|
||||
* the remaining values in the heap are re-sorted
|
||||
*/
|
||||
extractMin () {
|
||||
*/
|
||||
extractMin() {
|
||||
this.swap(0, this.heap.length - 1, this.heap)
|
||||
const min = this.heap.pop()
|
||||
this.sinkDown(0, this.heap.length - 1, this.heap)
|
||||
@ -110,13 +111,13 @@ class MinHeap {
|
||||
}
|
||||
|
||||
// a new value is pushed to the end of the heap and sorted up
|
||||
insert (value) {
|
||||
insert(value) {
|
||||
this.heap.push(value)
|
||||
this.bubbleUp(this.heap.length - 1)
|
||||
}
|
||||
|
||||
// index-swapping helper method
|
||||
swap (idx1, idx2, heap) {
|
||||
swap(idx1, idx2, heap) {
|
||||
const temp = heap[idx1]
|
||||
heap[idx1] = heap[idx2]
|
||||
heap[idx2] = temp
|
||||
|
@ -1,18 +1,18 @@
|
||||
/* Minimum Priority Queue
|
||||
* It is a part of heap data structure
|
||||
* A heap is a specific tree based data structure
|
||||
* in which all the nodes of tree are in a specific order.
|
||||
* that is the children are arranged in some
|
||||
* respect of their parents, can either be greater
|
||||
* or less than the parent. This makes it a min priority queue
|
||||
* or max priority queue.
|
||||
*/
|
||||
* It is a part of heap data structure
|
||||
* A heap is a specific tree based data structure
|
||||
* in which all the nodes of tree are in a specific order.
|
||||
* that is the children are arranged in some
|
||||
* respect of their parents, can either be greater
|
||||
* or less than the parent. This makes it a min priority queue
|
||||
* or max priority queue.
|
||||
*/
|
||||
|
||||
// Functions: insert, delete, peek, isEmpty, print, heapSort, sink
|
||||
|
||||
class MinPriorityQueue {
|
||||
// calls the constructor and initializes the capacity
|
||||
constructor (c) {
|
||||
constructor(c) {
|
||||
this.heap = []
|
||||
this.capacity = c
|
||||
this.size = 0
|
||||
@ -20,7 +20,7 @@ class MinPriorityQueue {
|
||||
|
||||
// inserts the key at the end and rearranges it
|
||||
// so that the binary heap is in appropriate order
|
||||
insert (key) {
|
||||
insert(key) {
|
||||
if (this.isFull()) return
|
||||
this.heap[this.size + 1] = key
|
||||
let k = this.size + 1
|
||||
@ -36,33 +36,36 @@ class MinPriorityQueue {
|
||||
}
|
||||
|
||||
// returns the highest priority value
|
||||
peek () {
|
||||
peek() {
|
||||
return this.heap[1]
|
||||
}
|
||||
|
||||
// returns boolean value whether the heap is empty or not
|
||||
isEmpty () {
|
||||
isEmpty() {
|
||||
return this.size === 0
|
||||
}
|
||||
|
||||
// returns boolean value whether the heap is full or not
|
||||
isFull () {
|
||||
isFull() {
|
||||
return this.size === this.capacity
|
||||
}
|
||||
|
||||
// prints the heap
|
||||
print (output = value => console.log(value)) {
|
||||
print(output = (value) => console.log(value)) {
|
||||
output(this.heap.slice(1))
|
||||
}
|
||||
|
||||
// heap reverse can be done by performing swapping the first
|
||||
// element with the last, removing the last element to
|
||||
// new array and calling sink function.
|
||||
heapReverse () {
|
||||
heapReverse() {
|
||||
const heapSort = []
|
||||
while (this.size > 0) {
|
||||
// swap first element with last element
|
||||
[this.heap[1], this.heap[this.size]] = [this.heap[this.size], this.heap[1]]
|
||||
;[this.heap[1], this.heap[this.size]] = [
|
||||
this.heap[this.size],
|
||||
this.heap[1]
|
||||
]
|
||||
heapSort.push(this.heap.pop())
|
||||
this.size--
|
||||
this.sink()
|
||||
@ -74,7 +77,7 @@ class MinPriorityQueue {
|
||||
}
|
||||
|
||||
// this function reorders the heap after every delete function
|
||||
sink () {
|
||||
sink() {
|
||||
let k = 1
|
||||
while (2 * k <= this.size || 2 * k + 1 <= this.size) {
|
||||
let minIndex
|
||||
@ -92,8 +95,7 @@ class MinPriorityQueue {
|
||||
this.heap[k] > this.heap[2 * k] ||
|
||||
this.heap[k] > this.heap[2 * k + 1]
|
||||
) {
|
||||
minIndex =
|
||||
this.heap[2 * k] < this.heap[2 * k + 1] ? 2 * k : 2 * k + 1
|
||||
minIndex = this.heap[2 * k] < this.heap[2 * k + 1] ? 2 * k : 2 * k + 1
|
||||
} else {
|
||||
minIndex = k
|
||||
}
|
||||
@ -107,7 +109,7 @@ class MinPriorityQueue {
|
||||
|
||||
// deletes the highest priority value from the heap. The last
|
||||
// element goes to ahead to first position and reorder heap
|
||||
delete () {
|
||||
delete() {
|
||||
// checks empty and one element array conditions
|
||||
if (this.isEmpty()) return
|
||||
if (this.size === 1) {
|
||||
|
@ -9,7 +9,9 @@ describe('MinHeap', () => {
|
||||
})
|
||||
|
||||
it('should initialize a heap from an input array', () => {
|
||||
expect(heap).toEqual({ 'heap': [1, 4, 2, 7, 16, 10, 39, 23, 9, 43, 85, 42, 51] }) // eslint-disable-line
|
||||
expect(heap).toEqual({
|
||||
heap: [1, 4, 2, 7, 16, 10, 39, 23, 9, 43, 85, 42, 51]
|
||||
}) // eslint-disable-line
|
||||
})
|
||||
|
||||
it('should show the top value in the heap', () => {
|
||||
@ -22,12 +24,14 @@ describe('MinHeap', () => {
|
||||
const minValue = heap.extractMin()
|
||||
|
||||
expect(minValue).toEqual(1)
|
||||
expect(heap).toEqual({ 'heap': [2, 4, 10, 7, 16, 42, 39, 23, 9, 43, 85, 51] }) // eslint-disable-line
|
||||
expect(heap).toEqual({ heap: [2, 4, 10, 7, 16, 42, 39, 23, 9, 43, 85, 51] }) // eslint-disable-line
|
||||
})
|
||||
|
||||
it('should insert a new value and sort until it meets heap conditions', () => {
|
||||
heap.insert(15)
|
||||
|
||||
expect(heap).toEqual({ 'heap': [2, 4, 10, 7, 16, 15, 39, 23, 9, 43, 85, 51, 42] }) // eslint-disable-line
|
||||
expect(heap).toEqual({
|
||||
heap: [2, 4, 10, 7, 16, 15, 39, 23, 9, 43, 85, 51, 42]
|
||||
}) // eslint-disable-line
|
||||
})
|
||||
})
|
||||
|
@ -7,11 +7,11 @@ describe('MinPriorityQueue', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
queue = new MinPriorityQueue(capacity)
|
||||
values.forEach(v => queue.insert(v))
|
||||
values.forEach((v) => queue.insert(v))
|
||||
})
|
||||
|
||||
it('Check heap ordering', () => {
|
||||
const mockFn = jest.fn()
|
||||
const mockFn = vi.fn()
|
||||
queue.print(mockFn)
|
||||
|
||||
expect(mockFn.mock.calls.length).toBe(1) // Expect one call
|
||||
@ -24,7 +24,7 @@ describe('MinPriorityQueue', () => {
|
||||
|
||||
it('heapSort() expected to reverse the heap ordering', () => {
|
||||
queue.heapReverse()
|
||||
const mockFn = jest.fn()
|
||||
const mockFn = vi.fn()
|
||||
queue.print(mockFn)
|
||||
|
||||
expect(mockFn.mock.calls.length).toBe(1)
|
||||
|
@ -14,11 +14,11 @@ Link for the Problem: https://leetcode.com/problems/add-two-numbers/
|
||||
*/
|
||||
|
||||
class AddTwoNumbers {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.dummyNode = new Node(0)
|
||||
}
|
||||
|
||||
solution (firstList, secondList) {
|
||||
solution(firstList, secondList) {
|
||||
let firstRunner = firstList
|
||||
let secondRunner = secondList
|
||||
let tail = this.dummyNode
|
||||
@ -44,7 +44,7 @@ class AddTwoNumbers {
|
||||
return this.dummyNode.next
|
||||
}
|
||||
|
||||
solutionToArray () {
|
||||
solutionToArray() {
|
||||
const list = []
|
||||
let currentNode = this.dummyNode.next
|
||||
while (currentNode) {
|
||||
|
@ -3,18 +3,22 @@
|
||||
* https://en.wikipedia.org/wiki/Cycle_detection
|
||||
*/
|
||||
|
||||
function detectCycle (head) {
|
||||
function detectCycle(head) {
|
||||
/*
|
||||
Problem Statement:
|
||||
Given head, the head of a linked list, determine if the linked list has a cycle in it.
|
||||
Link for the Problem: https://leetcode.com/problems/linked-list-cycle/
|
||||
*/
|
||||
if (!head) { return false }
|
||||
if (!head) {
|
||||
return false
|
||||
}
|
||||
|
||||
let slow = head
|
||||
let fast = head.next
|
||||
while (fast && fast.next) {
|
||||
if (fast === slow) { return true }
|
||||
if (fast === slow) {
|
||||
return true
|
||||
}
|
||||
fast = fast.next.next
|
||||
slow = slow.next
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
class Node {
|
||||
constructor (element) {
|
||||
constructor(element) {
|
||||
this.element = element
|
||||
this.next = null
|
||||
this.prev = null
|
||||
@ -7,14 +7,14 @@ class Node {
|
||||
}
|
||||
|
||||
class DoubleLinkedList {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.length = 0
|
||||
this.head = null
|
||||
this.tail = null
|
||||
}
|
||||
|
||||
// Add new element
|
||||
append (element) {
|
||||
append(element) {
|
||||
const node = new Node(element)
|
||||
|
||||
if (!this.head) {
|
||||
@ -30,7 +30,7 @@ class DoubleLinkedList {
|
||||
}
|
||||
|
||||
// Add element
|
||||
insert (position, element) {
|
||||
insert(position, element) {
|
||||
// Check of out-of-bound values
|
||||
if (position >= 0 && position <= this.length) {
|
||||
const node = new Node(element)
|
||||
@ -74,7 +74,7 @@ class DoubleLinkedList {
|
||||
}
|
||||
|
||||
// Remove element at any position
|
||||
removeAt (position) {
|
||||
removeAt(position) {
|
||||
// look for out-of-bounds value
|
||||
if (position > -1 && position < this.length) {
|
||||
let current = this.head
|
||||
@ -114,7 +114,7 @@ class DoubleLinkedList {
|
||||
}
|
||||
|
||||
// Get the indexOf item
|
||||
indexOf (elm) {
|
||||
indexOf(elm) {
|
||||
let current = this.head
|
||||
let index = -1
|
||||
|
||||
@ -133,27 +133,27 @@ class DoubleLinkedList {
|
||||
}
|
||||
|
||||
// Find the item in the list
|
||||
isPresent (elm) {
|
||||
isPresent(elm) {
|
||||
return this.indexOf(elm) !== -1
|
||||
}
|
||||
|
||||
// Delete an item from the list
|
||||
delete (elm) {
|
||||
delete(elm) {
|
||||
return this.removeAt(this.indexOf(elm))
|
||||
}
|
||||
|
||||
// Delete first item from the list
|
||||
deleteHead () {
|
||||
deleteHead() {
|
||||
this.removeAt(0)
|
||||
}
|
||||
|
||||
// Delete last item from the list
|
||||
deleteTail () {
|
||||
deleteTail() {
|
||||
this.removeAt(this.length - 1)
|
||||
}
|
||||
|
||||
// Print item of the string
|
||||
toString () {
|
||||
toString() {
|
||||
let current = this.head
|
||||
let string = ''
|
||||
|
||||
@ -166,7 +166,7 @@ class DoubleLinkedList {
|
||||
}
|
||||
|
||||
// Convert list to array
|
||||
toArray () {
|
||||
toArray() {
|
||||
const arr = []
|
||||
let current = this.head
|
||||
|
||||
@ -179,31 +179,31 @@ class DoubleLinkedList {
|
||||
}
|
||||
|
||||
// Check if list is empty
|
||||
isEmpty () {
|
||||
isEmpty() {
|
||||
return this.length === 0
|
||||
}
|
||||
|
||||
// Get the size of the list
|
||||
size () {
|
||||
size() {
|
||||
return this.length
|
||||
}
|
||||
|
||||
// Get the this.head
|
||||
getHead () {
|
||||
getHead() {
|
||||
return this.head
|
||||
}
|
||||
|
||||
// Get the this.tail
|
||||
getTail () {
|
||||
getTail() {
|
||||
return this.tail
|
||||
}
|
||||
|
||||
// Method to iterate over the LinkedList
|
||||
iterator () {
|
||||
iterator() {
|
||||
let currentNode = this.getHead()
|
||||
if (currentNode === null) return -1
|
||||
|
||||
const iterate = function * () {
|
||||
const iterate = function* () {
|
||||
while (currentNode) {
|
||||
yield currentNode.element
|
||||
currentNode = currentNode.next
|
||||
@ -214,7 +214,7 @@ class DoubleLinkedList {
|
||||
|
||||
// Method to log the LinkedList, for debugging
|
||||
// it' a circular structure, so can't use stringify to debug the whole structure
|
||||
log () {
|
||||
log() {
|
||||
let currentNode = this.getHead()
|
||||
while (currentNode) {
|
||||
console.log(currentNode.element)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** A LinkedList based solution to reverse a number
|
||||
Problem Statement: Given a number such that each of its digit is stored in a singly linked list. Reverse the linked list and return the head of the linked list Link for the Problem: https://leetcode.com/problems/reverse-linked-list/ */
|
||||
class ReverseSinglyLinkedList {
|
||||
solution (head) {
|
||||
solution(head) {
|
||||
let prev = null
|
||||
let next = null
|
||||
while (head) {
|
||||
@ -11,6 +11,6 @@ class ReverseSinglyLinkedList {
|
||||
head = next
|
||||
}
|
||||
return prev
|
||||
};
|
||||
}
|
||||
}
|
||||
export { ReverseSinglyLinkedList }
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Node } from './SinglyLinkedList.js'
|
||||
|
||||
class SinglyCircularLinkedList {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.headNode = null
|
||||
this.length = 0
|
||||
}
|
||||
@ -15,12 +15,12 @@ class SinglyCircularLinkedList {
|
||||
isEmpty = () => this.length === 0
|
||||
|
||||
// initiate the node and index
|
||||
initiateNodeAndIndex () {
|
||||
initiateNodeAndIndex() {
|
||||
return { currentNode: this.headNode, currentIndex: 0 }
|
||||
}
|
||||
|
||||
// get the data specific to an index
|
||||
getElementAt (index) {
|
||||
getElementAt(index) {
|
||||
if (this.length !== 0 && index >= 0 && index <= this.length) {
|
||||
let { currentNode } = this.initiateNodeAndIndex()
|
||||
for (let i = 0; i < index && currentNode !== null; i++) {
|
||||
@ -32,7 +32,7 @@ class SinglyCircularLinkedList {
|
||||
}
|
||||
|
||||
// Add the element in the first position
|
||||
addAtFirst (data) {
|
||||
addAtFirst(data) {
|
||||
const node = new Node(data)
|
||||
node.next = this.headNode
|
||||
this.headNode = node
|
||||
@ -41,8 +41,10 @@ class SinglyCircularLinkedList {
|
||||
}
|
||||
|
||||
// Add any data to the end of the linkedList
|
||||
add (data) {
|
||||
if (!this.headNode) { return this.addAtFirst(data) }
|
||||
add(data) {
|
||||
if (!this.headNode) {
|
||||
return this.addAtFirst(data)
|
||||
}
|
||||
const node = new Node(data)
|
||||
// Getting the last node
|
||||
const currentNode = this.getElementAt(this.length - 1)
|
||||
@ -53,10 +55,11 @@ class SinglyCircularLinkedList {
|
||||
}
|
||||
|
||||
// insert data at a specific position
|
||||
insertAt (index, data) {
|
||||
insertAt(index, data) {
|
||||
if (index === 0) return this.addAtFirst(data)
|
||||
if (index === this.length) return this.add(data)
|
||||
if (index < 0 || index > this.length) throw new RangeError(`Index is out of range max ${this.length}`)
|
||||
if (index < 0 || index > this.length)
|
||||
throw new RangeError(`Index is out of range max ${this.length}`)
|
||||
const node = new Node(data)
|
||||
const previousNode = this.getElementAt(index - 1)
|
||||
node.next = previousNode.next
|
||||
@ -66,7 +69,7 @@ class SinglyCircularLinkedList {
|
||||
}
|
||||
|
||||
// find the first index of the data
|
||||
indexOf (data) {
|
||||
indexOf(data) {
|
||||
let { currentNode } = this.initiateNodeAndIndex()
|
||||
// initializing currentIndex as -1
|
||||
let currentIndex = -1
|
||||
@ -81,7 +84,7 @@ class SinglyCircularLinkedList {
|
||||
}
|
||||
|
||||
// remove the data from the end of the list
|
||||
remove () {
|
||||
remove() {
|
||||
if (this.isEmpty()) return null
|
||||
const secondLastNode = this.getElementAt(this.length - 2)
|
||||
const removedNode = secondLastNode.next
|
||||
@ -91,7 +94,7 @@ class SinglyCircularLinkedList {
|
||||
}
|
||||
|
||||
// remove the data from the first of the list
|
||||
removeFirst () {
|
||||
removeFirst() {
|
||||
if (this.isEmpty()) return null
|
||||
const removedNode = this.headNode
|
||||
if (this.length === 1) {
|
||||
@ -106,7 +109,7 @@ class SinglyCircularLinkedList {
|
||||
}
|
||||
|
||||
// remove the data from the index
|
||||
removeAt (index) {
|
||||
removeAt(index) {
|
||||
if (this.isEmpty()) return null
|
||||
if (index === 0) return this.removeFirst()
|
||||
if (index === this.length) return this.remove()
|
||||
@ -119,14 +122,14 @@ class SinglyCircularLinkedList {
|
||||
}
|
||||
|
||||
// remove if the data is present
|
||||
removeData (data) {
|
||||
removeData(data) {
|
||||
if (this.isEmpty()) return null
|
||||
const index = this.indexOf(data)
|
||||
return this.removeAt(index)
|
||||
}
|
||||
|
||||
// logs the data
|
||||
printData (output = value => console.log(value)) {
|
||||
printData(output = (value) => console.log(value)) {
|
||||
let { currentIndex, currentNode } = this.initiateNodeAndIndex()
|
||||
|
||||
while (currentNode !== null && currentIndex < this.length) {
|
||||
@ -137,7 +140,7 @@ class SinglyCircularLinkedList {
|
||||
}
|
||||
|
||||
// get the data from the linkedList
|
||||
get () {
|
||||
get() {
|
||||
let { currentIndex, currentNode } = this.initiateNodeAndIndex()
|
||||
const list = []
|
||||
while (currentNode !== null && currentIndex < this.length) {
|
||||
@ -148,7 +151,7 @@ class SinglyCircularLinkedList {
|
||||
return list
|
||||
}
|
||||
|
||||
clear () {
|
||||
clear() {
|
||||
this.headNode = null
|
||||
this.length = 0
|
||||
}
|
||||
|
@ -9,14 +9,14 @@
|
||||
// Methods - size, head, addLast, addFirst, addAt, removeFirst, removeLast, remove, removeAt, indexOf, isEmpty, elementAt, findMiddle, get, clean, rotateListRight
|
||||
|
||||
class Node {
|
||||
constructor (data) {
|
||||
constructor(data) {
|
||||
this.data = data
|
||||
this.next = null
|
||||
}
|
||||
}
|
||||
|
||||
class LinkedList {
|
||||
constructor (listOfValues) {
|
||||
constructor(listOfValues) {
|
||||
this.headNode = null
|
||||
this.tailNode = null
|
||||
this.length = 0
|
||||
@ -29,32 +29,32 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// initiates the currentNode and currentIndex and return as an object
|
||||
initiateNodeAndIndex () {
|
||||
initiateNodeAndIndex() {
|
||||
return { currentNode: this.headNode, currentIndex: 0 }
|
||||
}
|
||||
|
||||
// Returns length
|
||||
size () {
|
||||
size() {
|
||||
return this.length
|
||||
}
|
||||
|
||||
// Returns the head
|
||||
head () {
|
||||
head() {
|
||||
return this.headNode?.data ?? null
|
||||
}
|
||||
|
||||
// Returns the tail
|
||||
tail () {
|
||||
tail() {
|
||||
return this.tailNode?.data ?? null
|
||||
}
|
||||
|
||||
// Return if the list is empty
|
||||
isEmpty () {
|
||||
isEmpty() {
|
||||
return this.length === 0
|
||||
}
|
||||
|
||||
// add a node at last it to linklist
|
||||
addLast (element) {
|
||||
addLast(element) {
|
||||
// Check if its the first element
|
||||
if (this.headNode === null) {
|
||||
return this.addFirst(element)
|
||||
@ -68,7 +68,7 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// add a node at first it to linklist
|
||||
addFirst (element) {
|
||||
addFirst(element) {
|
||||
const node = new Node(element)
|
||||
// Check if its the first element
|
||||
if (this.headNode === null) {
|
||||
@ -82,7 +82,7 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// remove the first from the linklist
|
||||
removeFirst () {
|
||||
removeFirst() {
|
||||
// Check if head is null
|
||||
if (this.headNode === null) {
|
||||
return null
|
||||
@ -99,7 +99,7 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// remove the last from the linklist
|
||||
removeLast () {
|
||||
removeLast() {
|
||||
if (this.isEmpty()) return null
|
||||
// Check if there is only one element
|
||||
if (this.length === 1) {
|
||||
@ -118,7 +118,7 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// Removes the node with the value as param
|
||||
remove (element) {
|
||||
remove(element) {
|
||||
if (this.isEmpty()) return null
|
||||
let { currentNode } = this.initiateNodeAndIndex()
|
||||
let removedNode = null
|
||||
@ -144,7 +144,7 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// Returns the index of the element passed as param otherwise -1
|
||||
indexOf (element) {
|
||||
indexOf(element) {
|
||||
if (this.isEmpty()) return -1
|
||||
let { currentNode, currentIndex } = this.initiateNodeAndIndex()
|
||||
while (currentNode) {
|
||||
@ -158,7 +158,7 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// Returns the element at an index
|
||||
elementAt (index) {
|
||||
elementAt(index) {
|
||||
if (index >= this.length || index < 0) {
|
||||
throw new RangeError('Out of Range index')
|
||||
}
|
||||
@ -171,7 +171,7 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// Adds the element at specified index
|
||||
addAt (index, element) {
|
||||
addAt(index, element) {
|
||||
// Check if index is out of bounds of list
|
||||
if (index > this.length || index < 0) {
|
||||
throw new RangeError('Out of Range index')
|
||||
@ -196,7 +196,7 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// Removes the node at specified index
|
||||
removeAt (index) {
|
||||
removeAt(index) {
|
||||
// Check if index is present in list
|
||||
if (index < 0 || index >= this.length) {
|
||||
throw new RangeError('Out of Range index')
|
||||
@ -216,7 +216,7 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// Returns a reference to middle node of linked list
|
||||
findMiddle () {
|
||||
findMiddle() {
|
||||
// If there are two middle nodes, return the second middle node.
|
||||
let fast = this.headNode
|
||||
let slow = this.headNode
|
||||
@ -229,14 +229,14 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// make the linkedList Empty
|
||||
clean () {
|
||||
clean() {
|
||||
this.headNode = null
|
||||
this.tailNode = null
|
||||
this.length = 0
|
||||
}
|
||||
|
||||
// Method to get the LinkedList
|
||||
get () {
|
||||
get() {
|
||||
const list = []
|
||||
let { currentNode } = this.initiateNodeAndIndex()
|
||||
while (currentNode) {
|
||||
@ -247,7 +247,7 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// Method for Rotating a List to the right by k places
|
||||
rotateListRight (k) {
|
||||
rotateListRight(k) {
|
||||
if (!this.headNode) return
|
||||
let current = this.headNode
|
||||
let tail = this.tailNode
|
||||
@ -268,11 +268,11 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// Method to iterate over the LinkedList
|
||||
iterator () {
|
||||
iterator() {
|
||||
let { currentNode } = this.initiateNodeAndIndex()
|
||||
if (currentNode === null) return -1
|
||||
|
||||
const iterate = function * () {
|
||||
const iterate = function* () {
|
||||
while (currentNode) {
|
||||
yield currentNode.data
|
||||
currentNode = currentNode.next
|
||||
@ -282,12 +282,12 @@ class LinkedList {
|
||||
}
|
||||
|
||||
// Method to log the LinkedList
|
||||
log () {
|
||||
log() {
|
||||
console.log(JSON.stringify(this.headNode, null, 2))
|
||||
}
|
||||
|
||||
// Method to reverse the LinkedList
|
||||
reverse () {
|
||||
reverse() {
|
||||
let head = this.headNode
|
||||
let prev = null
|
||||
let next = null
|
||||
@ -299,7 +299,7 @@ class LinkedList {
|
||||
}
|
||||
this.tailNode = this.headNode
|
||||
this.headNode = prev
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export { Node, LinkedList }
|
||||
|
@ -1,147 +1,147 @@
|
||||
import { SinglyCircularLinkedList } from '../SinglyCircularLinkedList'
|
||||
|
||||
describe('SinglyCircularLinkedList', () => {
|
||||
let list
|
||||
beforeEach(() => {
|
||||
list = new SinglyCircularLinkedList()
|
||||
})
|
||||
it('Check get', () => {
|
||||
expect(list.get()).toEqual([])
|
||||
expect(list.add(1)).toEqual(1)
|
||||
expect(list.get()).toEqual([1])
|
||||
expect(list.add(5)).toEqual(2)
|
||||
expect(list.get()).toEqual([1, 5])
|
||||
})
|
||||
|
||||
it('Check size', () => {
|
||||
expect(list.size()).toEqual(0)
|
||||
expect(list.add(1)).toEqual(1)
|
||||
expect(list.add(1)).toEqual(2)
|
||||
expect(list.size()).toEqual(2)
|
||||
})
|
||||
|
||||
it('Check head', () => {
|
||||
expect(list.head()).toEqual(null)
|
||||
expect(list.add(1)).toEqual(1)
|
||||
expect(list.head()).toEqual(1)
|
||||
expect(list.add(1)).toEqual(2)
|
||||
expect(list.head()).toEqual(1)
|
||||
expect(list.addAtFirst(100)).toEqual(3)
|
||||
expect(list.head()).toEqual(100)
|
||||
expect(list.insertAt(0, 500)).toEqual(4)
|
||||
expect(list.head()).toEqual(500)
|
||||
list.clear()
|
||||
expect(list.head()).toEqual(null)
|
||||
})
|
||||
|
||||
it('Check isEmpty', () => {
|
||||
expect(list.isEmpty()).toEqual(true)
|
||||
expect(list.add(1)).toEqual(1)
|
||||
expect(list.add(1)).toEqual(2)
|
||||
expect(list.isEmpty()).toEqual(false)
|
||||
})
|
||||
|
||||
it('Check getElementAt', () => {
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
|
||||
expect(list.getElementAt(1).data).toEqual(200)
|
||||
expect(list.getElementAt(3).data).toEqual(500)
|
||||
})
|
||||
|
||||
it('Check addAtFirst', () => {
|
||||
list.add(1)
|
||||
list.add(5)
|
||||
list.add(7)
|
||||
list.add(9)
|
||||
list.add(0)
|
||||
expect(list.get()).toEqual([1, 5, 7, 9, 0])
|
||||
list.addAtFirst(100)
|
||||
expect(list.get()).toEqual([100, 1, 5, 7, 9, 0])
|
||||
})
|
||||
|
||||
it('Check add', () => {
|
||||
list.add(1)
|
||||
list.add(5)
|
||||
list.add(7)
|
||||
list.add(9)
|
||||
list.add(0)
|
||||
expect(list.get()).toEqual([1, 5, 7, 9, 0])
|
||||
list.add(100)
|
||||
expect(list.get()).toEqual([1, 5, 7, 9, 0, 100])
|
||||
})
|
||||
|
||||
it('Check insertAt', () => {
|
||||
expect(list.insertAt(0, 100)).toEqual(1)
|
||||
expect(list.get()).toEqual([100])
|
||||
expect(list.insertAt(0, 200)).toEqual(2)
|
||||
expect(list.get()).toEqual([200, 100])
|
||||
expect(list.insertAt(2, 300)).toEqual(3)
|
||||
expect(list.get()).toEqual([200, 100, 300])
|
||||
})
|
||||
|
||||
it('Checks indexOf', () => {
|
||||
expect(list.indexOf(200)).toEqual(-1)
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
expect(list.indexOf(200)).toEqual(1)
|
||||
})
|
||||
|
||||
it('Check remove', () => {
|
||||
expect(list.remove()).toEqual(null)
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
expect(list.get()).toEqual([100, 200, 300, 500, 900])
|
||||
const removedData = list.remove()
|
||||
expect(removedData).toEqual(900)
|
||||
expect(list.get()).toEqual([100, 200, 300, 500])
|
||||
})
|
||||
|
||||
it('Check removeFirst', () => {
|
||||
expect(list.removeFirst()).toEqual(null)
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
expect(list.get()).toEqual([100, 200, 300, 500, 900])
|
||||
const removedData = list.removeFirst()
|
||||
expect(removedData).toEqual(100)
|
||||
expect(list.get()).toEqual([200, 300, 500, 900])
|
||||
})
|
||||
|
||||
it('Check removeAt', () => {
|
||||
expect(list.removeAt(1)).toEqual(null)
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
expect(list.get()).toEqual([100, 200, 300, 500, 900])
|
||||
const removedData = list.removeAt(2)
|
||||
expect(removedData).toEqual(300)
|
||||
expect(list.get()).toEqual([100, 200, 500, 900])
|
||||
})
|
||||
|
||||
it('Check removeData', () => {
|
||||
expect(list.removeData(100)).toEqual(null)
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
expect(list.get()).toEqual([100, 200, 300, 500, 900])
|
||||
const removedData = list.removeData(200)
|
||||
expect(removedData).toEqual(200)
|
||||
expect(list.get()).toEqual([100, 300, 500, 900])
|
||||
})
|
||||
})
|
||||
import { SinglyCircularLinkedList } from '../SinglyCircularLinkedList'
|
||||
|
||||
describe('SinglyCircularLinkedList', () => {
|
||||
let list
|
||||
beforeEach(() => {
|
||||
list = new SinglyCircularLinkedList()
|
||||
})
|
||||
it('Check get', () => {
|
||||
expect(list.get()).toEqual([])
|
||||
expect(list.add(1)).toEqual(1)
|
||||
expect(list.get()).toEqual([1])
|
||||
expect(list.add(5)).toEqual(2)
|
||||
expect(list.get()).toEqual([1, 5])
|
||||
})
|
||||
|
||||
it('Check size', () => {
|
||||
expect(list.size()).toEqual(0)
|
||||
expect(list.add(1)).toEqual(1)
|
||||
expect(list.add(1)).toEqual(2)
|
||||
expect(list.size()).toEqual(2)
|
||||
})
|
||||
|
||||
it('Check head', () => {
|
||||
expect(list.head()).toEqual(null)
|
||||
expect(list.add(1)).toEqual(1)
|
||||
expect(list.head()).toEqual(1)
|
||||
expect(list.add(1)).toEqual(2)
|
||||
expect(list.head()).toEqual(1)
|
||||
expect(list.addAtFirst(100)).toEqual(3)
|
||||
expect(list.head()).toEqual(100)
|
||||
expect(list.insertAt(0, 500)).toEqual(4)
|
||||
expect(list.head()).toEqual(500)
|
||||
list.clear()
|
||||
expect(list.head()).toEqual(null)
|
||||
})
|
||||
|
||||
it('Check isEmpty', () => {
|
||||
expect(list.isEmpty()).toEqual(true)
|
||||
expect(list.add(1)).toEqual(1)
|
||||
expect(list.add(1)).toEqual(2)
|
||||
expect(list.isEmpty()).toEqual(false)
|
||||
})
|
||||
|
||||
it('Check getElementAt', () => {
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
|
||||
expect(list.getElementAt(1).data).toEqual(200)
|
||||
expect(list.getElementAt(3).data).toEqual(500)
|
||||
})
|
||||
|
||||
it('Check addAtFirst', () => {
|
||||
list.add(1)
|
||||
list.add(5)
|
||||
list.add(7)
|
||||
list.add(9)
|
||||
list.add(0)
|
||||
expect(list.get()).toEqual([1, 5, 7, 9, 0])
|
||||
list.addAtFirst(100)
|
||||
expect(list.get()).toEqual([100, 1, 5, 7, 9, 0])
|
||||
})
|
||||
|
||||
it('Check add', () => {
|
||||
list.add(1)
|
||||
list.add(5)
|
||||
list.add(7)
|
||||
list.add(9)
|
||||
list.add(0)
|
||||
expect(list.get()).toEqual([1, 5, 7, 9, 0])
|
||||
list.add(100)
|
||||
expect(list.get()).toEqual([1, 5, 7, 9, 0, 100])
|
||||
})
|
||||
|
||||
it('Check insertAt', () => {
|
||||
expect(list.insertAt(0, 100)).toEqual(1)
|
||||
expect(list.get()).toEqual([100])
|
||||
expect(list.insertAt(0, 200)).toEqual(2)
|
||||
expect(list.get()).toEqual([200, 100])
|
||||
expect(list.insertAt(2, 300)).toEqual(3)
|
||||
expect(list.get()).toEqual([200, 100, 300])
|
||||
})
|
||||
|
||||
it('Checks indexOf', () => {
|
||||
expect(list.indexOf(200)).toEqual(-1)
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
expect(list.indexOf(200)).toEqual(1)
|
||||
})
|
||||
|
||||
it('Check remove', () => {
|
||||
expect(list.remove()).toEqual(null)
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
expect(list.get()).toEqual([100, 200, 300, 500, 900])
|
||||
const removedData = list.remove()
|
||||
expect(removedData).toEqual(900)
|
||||
expect(list.get()).toEqual([100, 200, 300, 500])
|
||||
})
|
||||
|
||||
it('Check removeFirst', () => {
|
||||
expect(list.removeFirst()).toEqual(null)
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
expect(list.get()).toEqual([100, 200, 300, 500, 900])
|
||||
const removedData = list.removeFirst()
|
||||
expect(removedData).toEqual(100)
|
||||
expect(list.get()).toEqual([200, 300, 500, 900])
|
||||
})
|
||||
|
||||
it('Check removeAt', () => {
|
||||
expect(list.removeAt(1)).toEqual(null)
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
expect(list.get()).toEqual([100, 200, 300, 500, 900])
|
||||
const removedData = list.removeAt(2)
|
||||
expect(removedData).toEqual(300)
|
||||
expect(list.get()).toEqual([100, 200, 500, 900])
|
||||
})
|
||||
|
||||
it('Check removeData', () => {
|
||||
expect(list.removeData(100)).toEqual(null)
|
||||
list.add(100)
|
||||
list.add(200)
|
||||
list.add(300)
|
||||
list.add(500)
|
||||
list.add(900)
|
||||
expect(list.get()).toEqual([100, 200, 300, 500, 900])
|
||||
const removedData = list.removeData(200)
|
||||
expect(removedData).toEqual(200)
|
||||
expect(list.get()).toEqual([100, 300, 500, 900])
|
||||
})
|
||||
})
|
||||
|
@ -4,7 +4,7 @@
|
||||
// Doesn’t use dynamic memory so No memory leaks
|
||||
|
||||
class CircularQueue {
|
||||
constructor (maxLength) {
|
||||
constructor(maxLength) {
|
||||
this.queue = []
|
||||
this.front = 0
|
||||
this.rear = 0
|
||||
@ -12,7 +12,7 @@ class CircularQueue {
|
||||
}
|
||||
|
||||
// ADD ELEMENTS TO QUEUE
|
||||
enqueue (value) {
|
||||
enqueue(value) {
|
||||
if (this.checkOverflow()) return
|
||||
if (this.checkEmpty()) {
|
||||
this.front += 1
|
||||
@ -26,7 +26,7 @@ class CircularQueue {
|
||||
}
|
||||
|
||||
// REMOVES ELEMENTS
|
||||
dequeue () {
|
||||
dequeue() {
|
||||
if (this.checkEmpty()) {
|
||||
// UNDERFLOW
|
||||
return
|
||||
@ -44,13 +44,13 @@ class CircularQueue {
|
||||
}
|
||||
|
||||
// checks if the queue is empty or not
|
||||
checkEmpty () {
|
||||
checkEmpty() {
|
||||
if (this.front === 0 && this.rear === 0) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
checkSingleelement () {
|
||||
checkSingleelement() {
|
||||
if (this.front === this.rear && this.rear !== 0) {
|
||||
this.front = this.rear = 0
|
||||
return true
|
||||
@ -58,27 +58,30 @@ class CircularQueue {
|
||||
}
|
||||
|
||||
// Checks if max capacity of queue has been reached or not
|
||||
checkOverflow () {
|
||||
if ((this.front === 1 && this.rear === this.maxLength) || (this.front === this.rear + 1)) {
|
||||
checkOverflow() {
|
||||
if (
|
||||
(this.front === 1 && this.rear === this.maxLength) ||
|
||||
this.front === this.rear + 1
|
||||
) {
|
||||
// CIRCULAR QUEUE OVERFLOW
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Prints the entire array ('*' represents blank space)
|
||||
display (output = value => console.log(value)) {
|
||||
display(output = (value) => console.log(value)) {
|
||||
for (let index = 1; index < this.queue.length; index++) {
|
||||
output(this.queue[index])
|
||||
}
|
||||
}
|
||||
|
||||
// Displays the length of queue
|
||||
length () {
|
||||
length() {
|
||||
return this.queue.length - 1
|
||||
}
|
||||
|
||||
// Display the top most value of queue
|
||||
peek () {
|
||||
peek() {
|
||||
return this.queue[this.front]
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
/* Queue
|
||||
* A Queue is a data structure that allows you to add an element to the end of
|
||||
* a list and remove the item at the front. A queue follows a FIFO (First In First Out)
|
||||
* system, where the first item to enter the queue is the first to be removed,
|
||||
* All these operation complexities are O(1).
|
||||
* This implementation following the linked list structure.
|
||||
*/
|
||||
* A Queue is a data structure that allows you to add an element to the end of
|
||||
* a list and remove the item at the front. A queue follows a FIFO (First In First Out)
|
||||
* system, where the first item to enter the queue is the first to be removed,
|
||||
* All these operation complexities are O(1).
|
||||
* This implementation following the linked list structure.
|
||||
*/
|
||||
|
||||
class Queue {
|
||||
#size
|
||||
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.head = null
|
||||
this.tail = null
|
||||
this.#size = 0
|
||||
@ -17,7 +17,7 @@ class Queue {
|
||||
return Object.seal(this)
|
||||
}
|
||||
|
||||
get length () {
|
||||
get length() {
|
||||
return this.#size
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ class Queue {
|
||||
* @param {*} data
|
||||
* @returns {number} - The current size of queue
|
||||
*/
|
||||
enqueue (data) {
|
||||
enqueue(data) {
|
||||
const node = { data, next: null }
|
||||
|
||||
if (!this.head && !this.tail) {
|
||||
@ -44,7 +44,7 @@ class Queue {
|
||||
* @description - Removes the value at the front of the queue
|
||||
* @returns {*} - The first data of the queue
|
||||
*/
|
||||
dequeue () {
|
||||
dequeue() {
|
||||
if (this.isEmpty()) {
|
||||
throw new Error('Queue is Empty')
|
||||
}
|
||||
@ -66,7 +66,7 @@ class Queue {
|
||||
* @description - Return the item at the front of the queue
|
||||
* @returns {*}
|
||||
*/
|
||||
peekFirst () {
|
||||
peekFirst() {
|
||||
if (this.isEmpty()) {
|
||||
throw new Error('Queue is Empty')
|
||||
}
|
||||
@ -78,7 +78,7 @@ class Queue {
|
||||
* @description - Return the item at the tail of the queue
|
||||
* @returns {*}
|
||||
*/
|
||||
peekLast () {
|
||||
peekLast() {
|
||||
if (this.isEmpty()) {
|
||||
throw new Error('Queue is Empty')
|
||||
}
|
||||
@ -90,7 +90,7 @@ class Queue {
|
||||
* @description - Return the array of Queue
|
||||
* @returns {Array<*>}
|
||||
*/
|
||||
toArray () {
|
||||
toArray() {
|
||||
const array = []
|
||||
let node = this.head
|
||||
|
||||
@ -103,10 +103,10 @@ class Queue {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description - Return is queue empty or not
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isEmpty () {
|
||||
* @description - Return is queue empty or not
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isEmpty() {
|
||||
return this.length === 0
|
||||
}
|
||||
}
|
||||
|
@ -2,17 +2,17 @@
|
||||
// contribution made by hamza chabchoub for a university project
|
||||
|
||||
class Queue {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.inputStack = []
|
||||
this.outputStack = []
|
||||
}
|
||||
|
||||
// Push item into the inputstack
|
||||
enqueue (item) {
|
||||
enqueue(item) {
|
||||
this.inputStack.push(item)
|
||||
}
|
||||
|
||||
dequeue () {
|
||||
dequeue() {
|
||||
// push all items to outputstack
|
||||
this.outputStack = []
|
||||
while (this.inputStack.length > 0) {
|
||||
@ -31,7 +31,7 @@ class Queue {
|
||||
}
|
||||
|
||||
// display elements of the inputstack
|
||||
listIn (output = value => console.log(value)) {
|
||||
listIn(output = (value) => console.log(value)) {
|
||||
let i = 0
|
||||
while (i < this.inputStack.length) {
|
||||
output(this.inputStack[i])
|
||||
@ -40,7 +40,7 @@ class Queue {
|
||||
}
|
||||
|
||||
// display element of the outputstack
|
||||
listOut (output = value => console.log(value)) {
|
||||
listOut(output = (value) => console.log(value)) {
|
||||
let i = 0
|
||||
while (i < this.outputStack.length) {
|
||||
output(this.outputStack[i])
|
||||
|
@ -1,15 +1,15 @@
|
||||
/* Stack!!
|
||||
* A stack is exactly what it sounds like. An element gets added to the top of
|
||||
* the stack and only the element on the top may be removed. This is an example
|
||||
* of an array implementation of a Stack. So an element can only be added/removed
|
||||
* from the end of the array.
|
||||
*/
|
||||
* A stack is exactly what it sounds like. An element gets added to the top of
|
||||
* the stack and only the element on the top may be removed. This is an example
|
||||
* of an array implementation of a Stack. So an element can only be added/removed
|
||||
* from the end of the array.
|
||||
*/
|
||||
|
||||
// Functions: push, pop, peek, view, length
|
||||
|
||||
// Creates a stack constructor
|
||||
const Stack = (function () {
|
||||
function Stack () {
|
||||
function Stack() {
|
||||
// The top of the Stack
|
||||
this.top = 0
|
||||
// The array representation of the stack
|
||||
@ -45,13 +45,13 @@ const Stack = (function () {
|
||||
}
|
||||
|
||||
// To see all the elements in the stack
|
||||
Stack.prototype.view = function (output = value => console.log(value)) {
|
||||
Stack.prototype.view = function (output = (value) => console.log(value)) {
|
||||
for (let i = 0; i < this.top; i++) {
|
||||
output(this.stack[i])
|
||||
}
|
||||
}
|
||||
|
||||
return Stack
|
||||
}())
|
||||
})()
|
||||
|
||||
export { Stack }
|
||||
|
@ -10,19 +10,19 @@
|
||||
|
||||
// Class declaration
|
||||
class Stack {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.stack = []
|
||||
this.top = 0
|
||||
}
|
||||
|
||||
// Adds a value to the end of the Stack
|
||||
push (newValue) {
|
||||
push(newValue) {
|
||||
this.stack.push(newValue)
|
||||
this.top += 1
|
||||
}
|
||||
|
||||
// Returns and removes the last element of the Stack
|
||||
pop () {
|
||||
pop() {
|
||||
if (this.top !== 0) {
|
||||
this.top -= 1
|
||||
return this.stack.pop()
|
||||
@ -31,17 +31,17 @@ class Stack {
|
||||
}
|
||||
|
||||
// Returns the number of elements in the Stack
|
||||
get length () {
|
||||
get length() {
|
||||
return this.top
|
||||
}
|
||||
|
||||
// Returns true if stack is empty, false otherwise
|
||||
get isEmpty () {
|
||||
get isEmpty() {
|
||||
return this.top === 0
|
||||
}
|
||||
|
||||
// Returns the last element without removing it
|
||||
get last () {
|
||||
get last() {
|
||||
if (this.top !== 0) {
|
||||
return this.stack[this.stack.length - 1]
|
||||
}
|
||||
@ -49,7 +49,7 @@ class Stack {
|
||||
}
|
||||
|
||||
// Checks if an object is the instance os the Stack class
|
||||
static isStack (el) {
|
||||
static isStack(el) {
|
||||
return el instanceof Stack
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,9 @@
|
||||
* RETURN > 0 if a > b
|
||||
* MUST RETURN 0 if a == b
|
||||
*/
|
||||
let utils;
|
||||
(function (_utils) {
|
||||
function comparator () {
|
||||
let utils
|
||||
;(function (_utils) {
|
||||
function comparator() {
|
||||
return function (v1, v2) {
|
||||
if (v1 < v2) return -1
|
||||
if (v2 < v1) return 1
|
||||
@ -32,7 +32,7 @@ let utils;
|
||||
* If no argument is sent it uses utils.comparator
|
||||
*/
|
||||
const AVLTree = (function () {
|
||||
function _avl (comp) {
|
||||
function _avl(comp) {
|
||||
/** @public comparator function */
|
||||
this._comp = undefined
|
||||
this._comp = comp !== undefined ? comp : utils.comparator()
|
||||
@ -53,7 +53,9 @@ const AVLTree = (function () {
|
||||
|
||||
// get height of a node
|
||||
const getHeight = function (node) {
|
||||
if (node == null) { return 0 }
|
||||
if (node == null) {
|
||||
return 0
|
||||
}
|
||||
return node._height
|
||||
}
|
||||
|
||||
@ -64,12 +66,15 @@ const AVLTree = (function () {
|
||||
|
||||
// update height of a node based on children's heights
|
||||
const updateHeight = function (node) {
|
||||
if (node == null) { return }
|
||||
if (node == null) {
|
||||
return
|
||||
}
|
||||
node._height = Math.max(getHeight(node._left), getHeight(node._right)) + 1
|
||||
}
|
||||
|
||||
// Helper: To check if the balanceFactor is valid
|
||||
const isValidBalanceFactor = (balanceFactor) => [0, 1, -1].includes(balanceFactor)
|
||||
const isValidBalanceFactor = (balanceFactor) =>
|
||||
[0, 1, -1].includes(balanceFactor)
|
||||
|
||||
// rotations of AVL Tree
|
||||
const leftRotate = function (node) {
|
||||
@ -140,13 +145,18 @@ const AVLTree = (function () {
|
||||
}
|
||||
updateHeight(root)
|
||||
const balanceFactor = getHeightDifference(root)
|
||||
return isValidBalanceFactor(balanceFactor) ? root : insertBalance(root, val, balanceFactor, tree)
|
||||
return isValidBalanceFactor(balanceFactor)
|
||||
? root
|
||||
: insertBalance(root, val, balanceFactor, tree)
|
||||
}
|
||||
|
||||
// delete am element
|
||||
const deleteElement = function (root, _val, tree) {
|
||||
if (root == null) { return root }
|
||||
if (tree._comp(root._val, _val) === 0) { // key found case
|
||||
if (root == null) {
|
||||
return root
|
||||
}
|
||||
if (tree._comp(root._val, _val) === 0) {
|
||||
// key found case
|
||||
if (root._left === null && root._right === null) {
|
||||
root = null
|
||||
tree.size--
|
||||
@ -177,7 +187,9 @@ const AVLTree = (function () {
|
||||
}
|
||||
// search tree for a element
|
||||
const searchAVLTree = function (root, val, tree) {
|
||||
if (root == null) { return null }
|
||||
if (root == null) {
|
||||
return null
|
||||
}
|
||||
if (tree._comp(root._val, val) === 0) {
|
||||
return root
|
||||
}
|
||||
@ -222,7 +234,7 @@ const AVLTree = (function () {
|
||||
return prevSize !== this.size
|
||||
}
|
||||
return _avl
|
||||
}())
|
||||
})()
|
||||
|
||||
/**
|
||||
* A Code for Testing the AVLTree
|
||||
|
@ -1,19 +1,19 @@
|
||||
/* Binary Search Tree!!
|
||||
*
|
||||
* Nodes that will go on the Binary Tree.
|
||||
* They consist of the data in them, the node to the left, the node
|
||||
* to the right, and the parent from which they came from.
|
||||
*
|
||||
* A binary tree is a data structure in which an element
|
||||
* has two successors(children). The left child is usually
|
||||
* smaller than the parent, and the right child is usually
|
||||
* bigger.
|
||||
*/
|
||||
*
|
||||
* Nodes that will go on the Binary Tree.
|
||||
* They consist of the data in them, the node to the left, the node
|
||||
* to the right, and the parent from which they came from.
|
||||
*
|
||||
* A binary tree is a data structure in which an element
|
||||
* has two successors(children). The left child is usually
|
||||
* smaller than the parent, and the right child is usually
|
||||
* bigger.
|
||||
*/
|
||||
|
||||
// class Node
|
||||
const Node = (function Node () {
|
||||
const Node = (function Node() {
|
||||
// Node in the tree
|
||||
function Node (val) {
|
||||
function Node(val) {
|
||||
this.value = val
|
||||
this.left = null
|
||||
this.right = null
|
||||
@ -32,7 +32,7 @@ const Node = (function Node () {
|
||||
}
|
||||
|
||||
// Visit a node
|
||||
Node.prototype.visit = function (output = value => console.log(value)) {
|
||||
Node.prototype.visit = function (output = (value) => console.log(value)) {
|
||||
// Recursively go left
|
||||
if (this.left !== null) {
|
||||
this.left.visit()
|
||||
@ -103,14 +103,14 @@ const Node = (function Node () {
|
||||
}
|
||||
// returns the constructor
|
||||
return Node
|
||||
}())
|
||||
})()
|
||||
|
||||
// class Tree
|
||||
const Tree = (function () {
|
||||
function Tree () {
|
||||
function Tree() {
|
||||
// Just store the root
|
||||
this.root = null
|
||||
};
|
||||
}
|
||||
|
||||
// Inorder traversal
|
||||
Tree.prototype.traverse = function () {
|
||||
@ -149,6 +149,6 @@ const Tree = (function () {
|
||||
|
||||
// returns the constructor
|
||||
return Tree
|
||||
}())
|
||||
})()
|
||||
|
||||
export { Tree }
|
||||
|
@ -13,7 +13,7 @@
|
||||
class SegmentTree {
|
||||
size
|
||||
tree
|
||||
constructor (arr) {
|
||||
constructor(arr) {
|
||||
// we define tree like this
|
||||
// tree[1] : root node of tree
|
||||
// tree[i] : i'th node
|
||||
@ -28,7 +28,7 @@ class SegmentTree {
|
||||
}
|
||||
|
||||
// function to build the tree
|
||||
build (arr) {
|
||||
build(arr) {
|
||||
const { size, tree } = this
|
||||
// insert leaf nodes in tree
|
||||
// leaf nodes will start from index N
|
||||
@ -45,7 +45,7 @@ class SegmentTree {
|
||||
}
|
||||
}
|
||||
|
||||
update (index, value) {
|
||||
update(index, value) {
|
||||
const { size, tree } = this
|
||||
|
||||
// only update values in the parents of the given node being changed.
|
||||
@ -65,7 +65,7 @@ class SegmentTree {
|
||||
}
|
||||
|
||||
// interval [L,R) with left index(L) included and right (R) excluded.
|
||||
query (left, right) {
|
||||
query(left, right) {
|
||||
const { size, tree } = this
|
||||
// cause R is excluded, increase right for convenient
|
||||
right++
|
||||
|
@ -1,4 +1,4 @@
|
||||
const TrieNode = function TrieNode (key, parent) {
|
||||
const TrieNode = function TrieNode(key, parent) {
|
||||
this.key = key
|
||||
this.count = 0
|
||||
this.children = Object.create(null)
|
||||
@ -9,7 +9,7 @@ const TrieNode = function TrieNode (key, parent) {
|
||||
}
|
||||
}
|
||||
|
||||
function Trie () {
|
||||
function Trie() {
|
||||
// create only root with null key and parent
|
||||
this.root = new TrieNode(null, null)
|
||||
}
|
||||
@ -18,7 +18,9 @@ function Trie () {
|
||||
Trie.findAllWords = function (root, word, output) {
|
||||
if (root === null) return
|
||||
if (root.count > 0) {
|
||||
if (typeof output === 'object') { output.push({ word, count: root.count }) }
|
||||
if (typeof output === 'object') {
|
||||
output.push({ word, count: root.count })
|
||||
}
|
||||
}
|
||||
let key
|
||||
for (key in root.children) {
|
||||
@ -38,7 +40,9 @@ Trie.prototype.insert = function (word) {
|
||||
const len = word.length
|
||||
let i
|
||||
for (i = 0; i < len; i++) {
|
||||
if (node.children[word.charAt(i)] === undefined) { node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node) }
|
||||
if (node.children[word.charAt(i)] === undefined) {
|
||||
node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node)
|
||||
}
|
||||
node = node.children[word.charAt(i)]
|
||||
}
|
||||
node.count += 1
|
||||
@ -87,7 +91,11 @@ Trie.prototype.remove = function (word, count) {
|
||||
// if the object forms some other objects prefix we don't delete it
|
||||
// For checking an empty object
|
||||
// https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object
|
||||
if (child.count <= 0 && (Object.keys(child.children).length && child.children.constructor === Object)) {
|
||||
if (
|
||||
child.count <= 0 &&
|
||||
Object.keys(child.children).length &&
|
||||
child.children.constructor === Object
|
||||
) {
|
||||
child.parent.children[child.key] = undefined
|
||||
}
|
||||
}
|
||||
|
@ -12,14 +12,14 @@ describe('AVLTree Implementation: ', () => {
|
||||
const emptyTree = new AVLTree(collator.compare)
|
||||
|
||||
beforeAll(() => {
|
||||
demoData.forEach(item => {
|
||||
demoData.forEach((item) => {
|
||||
if (avlTree.add(item)) {
|
||||
dataList.push(item)
|
||||
}
|
||||
})
|
||||
|
||||
avlStringTree._comp = collator.compare
|
||||
stringData.forEach(item => avlStringTree.add(item))
|
||||
stringData.forEach((item) => avlStringTree.add(item))
|
||||
})
|
||||
|
||||
it('delete and search from empty tree', () => {
|
||||
@ -33,10 +33,10 @@ describe('AVLTree Implementation: ', () => {
|
||||
})
|
||||
|
||||
it('search if inserted element is present', () => {
|
||||
demoData.forEach(data => {
|
||||
demoData.forEach((data) => {
|
||||
expect(avlTree.find(data)).toBeTruthy()
|
||||
})
|
||||
stringData.forEach(data => {
|
||||
stringData.forEach((data) => {
|
||||
expect(avlStringTree.find(data)).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
class Vector2 {
|
||||
constructor (x, y) {
|
||||
constructor(x, y) {
|
||||
this.x = x
|
||||
this.y = y
|
||||
}
|
||||
@ -17,7 +17,7 @@ class Vector2 {
|
||||
* @param vector The vector to compare to.
|
||||
* @returns Whether they are exactly equal or not.
|
||||
*/
|
||||
equalsExactly (vector) {
|
||||
equalsExactly(vector) {
|
||||
return this.x === vector.x && this.y === vector.y
|
||||
}
|
||||
|
||||
@ -28,8 +28,11 @@ class Vector2 {
|
||||
* @param epsilon The allowed discrepancy for the x-values and the y-values.
|
||||
* @returns Whether they are approximately equal or not.
|
||||
*/
|
||||
equalsApproximately (vector, epsilon) {
|
||||
return (Math.abs(this.x - vector.x) < epsilon && Math.abs(this.y - vector.y) < epsilon)
|
||||
equalsApproximately(vector, epsilon) {
|
||||
return (
|
||||
Math.abs(this.x - vector.x) < epsilon &&
|
||||
Math.abs(this.y - vector.y) < epsilon
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,7 +40,7 @@ class Vector2 {
|
||||
*
|
||||
* @returns The length of the vector.
|
||||
*/
|
||||
length () {
|
||||
length() {
|
||||
return Math.sqrt(this.x * this.x + this.y * this.y)
|
||||
}
|
||||
|
||||
@ -46,7 +49,7 @@ class Vector2 {
|
||||
*
|
||||
* @returns The normalized vector.
|
||||
*/
|
||||
normalize () {
|
||||
normalize() {
|
||||
const length = this.length()
|
||||
if (length === 0) {
|
||||
throw new Error('Cannot normalize vectors of length 0')
|
||||
@ -60,7 +63,7 @@ class Vector2 {
|
||||
* @param vector The vector to be added.
|
||||
* @returns The sum-vector.
|
||||
*/
|
||||
add (vector) {
|
||||
add(vector) {
|
||||
const x = this.x + vector.x
|
||||
const y = this.y + vector.y
|
||||
return new Vector2(x, y)
|
||||
@ -72,7 +75,7 @@ class Vector2 {
|
||||
* @param vector The vector to be subtracted.
|
||||
* @returns The difference-vector.
|
||||
*/
|
||||
subtract (vector) {
|
||||
subtract(vector) {
|
||||
const x = this.x - vector.x
|
||||
const y = this.y - vector.y
|
||||
return new Vector2(x, y)
|
||||
@ -84,7 +87,7 @@ class Vector2 {
|
||||
* @param scalar The factor by which to multiply the vector.
|
||||
* @returns The scaled vector.
|
||||
*/
|
||||
multiply (scalar) {
|
||||
multiply(scalar) {
|
||||
const x = this.x * scalar
|
||||
const y = this.y * scalar
|
||||
return new Vector2(x, y)
|
||||
@ -96,7 +99,7 @@ class Vector2 {
|
||||
* @param vector The vector to which to calculate the distance.
|
||||
* @returns The distance.
|
||||
*/
|
||||
distance (vector) {
|
||||
distance(vector) {
|
||||
const difference = vector.subtract(this)
|
||||
return difference.length()
|
||||
}
|
||||
@ -107,7 +110,7 @@ class Vector2 {
|
||||
* @param vector The vector used for the multiplication.
|
||||
* @returns The resulting dot product.
|
||||
*/
|
||||
dotProduct (vector) {
|
||||
dotProduct(vector) {
|
||||
return this.x * vector.x + this.y * vector.y
|
||||
}
|
||||
|
||||
@ -117,7 +120,7 @@ class Vector2 {
|
||||
* @param angleInRadians The angle in radians by which to rotate the vector.
|
||||
* @returns The rotated vector.
|
||||
*/
|
||||
rotate (angleInRadians) {
|
||||
rotate(angleInRadians) {
|
||||
const ca = Math.cos(angleInRadians)
|
||||
const sa = Math.sin(angleInRadians)
|
||||
const x = ca * this.x - sa * this.y
|
||||
@ -131,7 +134,7 @@ class Vector2 {
|
||||
* @param vector The 2nd vector for the measurement.
|
||||
* @returns The angle in radians.
|
||||
*/
|
||||
angleBetween (vector) {
|
||||
angleBetween(vector) {
|
||||
return Math.atan2(vector.y, vector.x) - Math.atan2(this.y, this.x)
|
||||
}
|
||||
}
|
||||
|
@ -5,52 +5,80 @@ describe('Vector2', () => {
|
||||
it('should compare equality correctly', () => {
|
||||
expect(new Vector2(1, 0).equalsExactly(new Vector2(1, 0))).toBe(true)
|
||||
|
||||
expect(new Vector2(1.23, 4.56).equalsExactly(new Vector2(0, 0))).toBe(false)
|
||||
expect(new Vector2(1.23, 4.56).equalsExactly(new Vector2(0, 0))).toBe(
|
||||
false
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#equalsApproximately', () => {
|
||||
it('should compare equality (approximately) correctly', () => {
|
||||
expect(new Vector2(1, 0).equalsApproximately(new Vector2(1, 0.0000001), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(1, 0).equalsApproximately(
|
||||
new Vector2(1, 0.0000001),
|
||||
0.000001
|
||||
)
|
||||
).toBe(true)
|
||||
|
||||
expect(new Vector2(1.23, 4.56).equalsApproximately(new Vector2(1.24, 4.56), 0.000001))
|
||||
.toBe(false)
|
||||
expect(
|
||||
new Vector2(1.23, 4.56).equalsApproximately(
|
||||
new Vector2(1.24, 4.56),
|
||||
0.000001
|
||||
)
|
||||
).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#add', () => {
|
||||
it('should add two vectors correctly', () => {
|
||||
expect(new Vector2(1, 0).add(new Vector2(0, 1)).equalsApproximately(new Vector2(1, 1), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(1, 0)
|
||||
.add(new Vector2(0, 1))
|
||||
.equalsApproximately(new Vector2(1, 1), 0.000001)
|
||||
).toBe(true)
|
||||
|
||||
expect(new Vector2(-3.3, -9).add(new Vector2(-2.2, 3)).equalsApproximately(new Vector2(-5.5, -6), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(-3.3, -9)
|
||||
.add(new Vector2(-2.2, 3))
|
||||
.equalsApproximately(new Vector2(-5.5, -6), 0.000001)
|
||||
).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#subtract', () => {
|
||||
it('should subtract two vectors correctly', () => {
|
||||
expect(new Vector2(1, 0).subtract(new Vector2(0, 1)).equalsApproximately(new Vector2(1, -1), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(1, 0)
|
||||
.subtract(new Vector2(0, 1))
|
||||
.equalsApproximately(new Vector2(1, -1), 0.000001)
|
||||
).toBe(true)
|
||||
|
||||
expect(new Vector2(234.5, 1.7).subtract(new Vector2(3.3, 2.7)).equalsApproximately(new Vector2(231.2, -1), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(234.5, 1.7)
|
||||
.subtract(new Vector2(3.3, 2.7))
|
||||
.equalsApproximately(new Vector2(231.2, -1), 0.000001)
|
||||
).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#multiply', () => {
|
||||
it('should multiply two vectors correctly', () => {
|
||||
expect(new Vector2(1, 0).multiply(5).equalsApproximately(new Vector2(5, 0), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(1, 0)
|
||||
.multiply(5)
|
||||
.equalsApproximately(new Vector2(5, 0), 0.000001)
|
||||
).toBe(true)
|
||||
|
||||
expect(new Vector2(3.41, -7.12).multiply(-3.1).equalsApproximately(new Vector2(-10.571, 22.072), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(3.41, -7.12)
|
||||
.multiply(-3.1)
|
||||
.equalsApproximately(new Vector2(-10.571, 22.072), 0.000001)
|
||||
).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#length', () => {
|
||||
it('should calculate it\'s length correctly', () => {
|
||||
it("should calculate it's length correctly", () => {
|
||||
expect(new Vector2(1, 0).length()).toBe(1)
|
||||
|
||||
expect(new Vector2(-1, 1).length()).toBe(Math.sqrt(2))
|
||||
@ -59,11 +87,20 @@ describe('Vector2', () => {
|
||||
|
||||
describe('#normalize', () => {
|
||||
it('should normalize vectors correctly', () => {
|
||||
expect(new Vector2(1, 0).normalize().equalsApproximately(new Vector2(1, 0), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(1, 0)
|
||||
.normalize()
|
||||
.equalsApproximately(new Vector2(1, 0), 0.000001)
|
||||
).toBe(true)
|
||||
|
||||
expect(new Vector2(1, -1).normalize().equalsApproximately(new Vector2(Math.sqrt(2) / 2, -Math.sqrt(2) / 2), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(1, -1)
|
||||
.normalize()
|
||||
.equalsApproximately(
|
||||
new Vector2(Math.sqrt(2) / 2, -Math.sqrt(2) / 2),
|
||||
0.000001
|
||||
)
|
||||
).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
@ -85,19 +122,29 @@ describe('Vector2', () => {
|
||||
|
||||
describe('#rotate', () => {
|
||||
it('should rotate a vector correctly', () => {
|
||||
expect(new Vector2(0, -1).rotate(Math.PI / 2).equalsApproximately(new Vector2(1, 0), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(0, -1)
|
||||
.rotate(Math.PI / 2)
|
||||
.equalsApproximately(new Vector2(1, 0), 0.000001)
|
||||
).toBe(true)
|
||||
|
||||
expect(new Vector2(1.23, -4.56).rotate(Math.PI).equalsApproximately(new Vector2(-1.23, 4.56), 0.000001))
|
||||
.toBe(true)
|
||||
expect(
|
||||
new Vector2(1.23, -4.56)
|
||||
.rotate(Math.PI)
|
||||
.equalsApproximately(new Vector2(-1.23, 4.56), 0.000001)
|
||||
).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#angleBetween', () => {
|
||||
it('should calculate the angle between two vectors correctly', () => {
|
||||
expect(new Vector2(1, 0).angleBetween(new Vector2(0, 1))).toBe(Math.PI / 2)
|
||||
expect(new Vector2(1, 0).angleBetween(new Vector2(0, 1))).toBe(
|
||||
Math.PI / 2
|
||||
)
|
||||
|
||||
expect(new Vector2(1, 0).angleBetween(new Vector2(1, -1))).toBe(-Math.PI / 4)
|
||||
expect(new Vector2(1, 0).angleBetween(new Vector2(1, -1))).toBe(
|
||||
-Math.PI / 4
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user