priority-queue
Advanced tools
| # This is a basic workflow to help you get started with Actions | ||
| name: CI | ||
| # Controls when the workflow will run | ||
| on: | ||
| # Triggers the workflow on push or pull request events but only for the main branch | ||
| push: | ||
| branches: [ main ] | ||
| # Allows you to run this workflow manually from the Actions tab | ||
| workflow_dispatch: | ||
| # A workflow run is made up of one or more jobs that can run sequentially or in parallel | ||
| jobs: | ||
| # This workflow contains a single job called "build" | ||
| build: | ||
| # The type of runner that the job will run on | ||
| runs-on: ubuntu-latest | ||
| # Steps represent a sequence of tasks that will be executed as part of the job | ||
| steps: | ||
| # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it | ||
| - uses: actions/checkout@v2 | ||
| # Runs a single command using the runners shell | ||
| - name: setup | ||
| run: npm install | ||
| # Runs a single command using the runners shell | ||
| - name: tests | ||
| run: npm test |
+36
| import PQ from './priority-queue.js' | ||
| function randomInt (min, max) { | ||
| return min + Math.round((max - min) * Math.random()) | ||
| } | ||
| const TEST_COUNT = 20000 | ||
| console.log(`Fuzzing ${TEST_COUNT} iterations`) | ||
| for (let i=0; i < TEST_COUNT; i++) { | ||
| const itemCount = randomInt(1, 1000) | ||
| const queue = PQ.create(itemCount) | ||
| // add itemCount items with random values | ||
| for (let i = 0; i < itemCount; i++) { | ||
| const val = Math.random() | ||
| const priority = val | ||
| PQ.queue(queue, val, priority) | ||
| } | ||
| // remove the items in order | ||
| let output = [ ] | ||
| for (let i = 0; i < itemCount; i++) | ||
| output.push(PQ.dequeue(queue)) | ||
| for (let i = 0; i < itemCount; i++) | ||
| if (i > 0 && output[i] > output[i-1]) | ||
| throw new Error(`priority not respected in this run; ${output[i]} > ${output[i-1]}`) | ||
| } | ||
| console.log('Fuzzing completed without errors') |
+9
-0
@@ -0,1 +1,10 @@ | ||
| ## 0.2.0 | ||
| * BREAKING: queue(...) requires priority as the 3rd argument, no longer optional | ||
| * BREAKING: comparator functions are removed. They are confusing and error-prone. Just pass a simple priority value instead | ||
| * BREAKING: priority-queue is now always a max-heap,(i.e.,dequeue(...) always returns highest priority item.) If you want a min-heap, use negative priority values. | ||
| * fix issue #2 | ||
| * add fuzz testing | ||
| * update mocha dep | ||
| ## 0.1.0 | ||
@@ -2,0 +11,0 @@ * package maintenance taken over by mreinstein |
+1
-1
| MIT License | ||
| Copyright (c) 2021 Mike Reinstein | ||
| Copyright (c) 2022 Mike Reinstein | ||
@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
+6
-4
| { | ||
| "name": "priority-queue", | ||
| "version": "0.1.0", | ||
| "version": "0.2.0", | ||
| "description": "functional, data oriented priority queue that doesn't suck", | ||
@@ -8,3 +8,5 @@ "main": "priority-queue.js", | ||
| "scripts": { | ||
| "test": "mocha test.js", | ||
| "test": "npm-run-all -s test:*", | ||
| "test:unit": "mocha test.js", | ||
| "test:fuzz": "node test-fuzz.js", | ||
| "prepublishOnly": "npm test" | ||
@@ -28,5 +30,5 @@ }, | ||
| "devDependencies": { | ||
| "mocha": "^8.3.2" | ||
| "mocha": "^10.0.0", | ||
| "npm-run-all": "^4.1.5" | ||
| }, | ||
| "dependencies": {}, | ||
| "engines": { | ||
@@ -33,0 +35,0 @@ "node": ">=12.17" |
+117
-28
@@ -1,33 +0,107 @@ | ||
| import Heap from './heap.js' | ||
| import removeItem from './remove-array-item.js' | ||
| function create (maxLength=1000) { | ||
| return { | ||
| arr: new Array(maxLength), | ||
| length: 0, | ||
| maxLength, | ||
| } | ||
| } | ||
| // creates a new priority queue data structure | ||
| function create (comparator, maxLength=1000) { | ||
| return Heap.create(comparator, maxLength) | ||
| function queue (heap, item, priority) { | ||
| if (priority === undefined) | ||
| throw new Error('must include priority when queueing') | ||
| if (_findIndex(heap, item) >= 0) { | ||
| del(heap, item) | ||
| } | ||
| if (heap.length === heap.maxLength) { | ||
| return | ||
| } | ||
| heap.arr[heap.length] = { item, priority } | ||
| heap.length++ | ||
| _upHeap(heap, heap.length-1) | ||
| } | ||
| function _findIndex (arr, length, needle) { | ||
| for (let i=0; i < length; i++) | ||
| if (arr[i].val === needle) | ||
| return i | ||
| return -1 | ||
| // traverse up the heap from a starting index | ||
| // | ||
| // heap | ||
| // index to start at | ||
| function _upHeap (heap, index) { | ||
| while (index > 0) { | ||
| let parentIdx | ||
| if (index % 2 === 0) | ||
| parentIdx = (index - 2) / 2 | ||
| else | ||
| parentIdx = (index - 1) / 2 | ||
| // if the parent is greater than the current node, stop because we've corrected the heap | ||
| if (heap.arr[parentIdx].priority >= heap.arr[index].priority) | ||
| return | ||
| _swap(heap.arr, index, parentIdx) | ||
| index = parentIdx | ||
| } | ||
| } | ||
| function queue (heap, val, priority) { | ||
| // TODO: consider checking existing priority. If it's the same, no point in deleting and re-inserting | ||
| if (_findIndex(heap.arr, heap.length, val) >= 0) | ||
| del(heap, val) | ||
| // get and remove highest priority item from the heap | ||
| function dequeue (heap) { | ||
| if (heap.length === 0) | ||
| return | ||
| Heap.insert(heap, { val, priority }) | ||
| const max = heap.arr[0].item | ||
| heap.length-- | ||
| heap.arr[0] = heap.arr[heap.length] | ||
| _downHeap(heap, 0) | ||
| return max | ||
| } | ||
| function dequeue (heap, dequeueHighest=true) { | ||
| return Heap.poll(heap, dequeueHighest) | ||
| // traverse down the heap from a starting index | ||
| // | ||
| // heap | ||
| // index to start at | ||
| function _downHeap (heap, index) { | ||
| while (index < heap.length) { | ||
| const left = index * 2 + 1 | ||
| const right = index * 2 + 2 | ||
| let largest = index | ||
| if (left <= heap.length && heap.arr[left].priority > heap.arr[largest].priority) | ||
| largest = left | ||
| if (right <= heap.length && heap.arr[right].priority > heap.arr[largest].priority) | ||
| largest = right | ||
| if (largest === index) | ||
| return | ||
| _swap(heap.arr, index, largest) | ||
| index = largest | ||
| } | ||
| } | ||
| function _swap (arr, i, j) { | ||
| const tmp = arr[i] | ||
| arr[i] = arr[j] | ||
| arr[j] = tmp | ||
| } | ||
| function clear (heap) { | ||
@@ -43,18 +117,36 @@ heap.length = 0 | ||
| function peek (heap, dequeueHighest=true) { | ||
| return Heap.peek(heap, dequeueHighest) | ||
| function peek (heap) { | ||
| if (!heap.length) | ||
| return | ||
| return heap.arr[0].item | ||
| } | ||
| function del (heap, k) { | ||
| const ind = _findIndex(heap.arr, heap.length, k) | ||
| function del (heap, item) { | ||
| const ind = _findIndex(heap, item) | ||
| if (ind < 0) | ||
| throw new Error('key does not exist!') | ||
| throw new Error('key does not exist in priority queue!') | ||
| removeItem(heap.arr, heap.length, ind) | ||
| const tmp = heap.arr[ind] | ||
| heap.arr[ind] = heap.arr[heap.length-1] | ||
| heap.arr[heap.length-1] = tmp | ||
| if (heap.arr[ind].priority > heap.arr[heap.length-1].priority) | ||
| _upHeap(heap, ind) | ||
| else if (heap.arr[ind].priority < heap.arr[heap.length-1].priority) | ||
| _downHeap(heap, ind) | ||
| heap.length-- | ||
| Heap.callHeapify(heap) | ||
| } | ||
| function _findIndex (heap, item) { | ||
| for (let i=0; i < heap.length; i++) | ||
| if (heap.arr[i].item === item) | ||
| return i | ||
| return -1 | ||
| } | ||
| function list (heap) { | ||
@@ -64,8 +156,5 @@ if (!heap.length) | ||
| if (heap.arr[0].priority) | ||
| return heap.arr.slice(0, heap.length) | ||
| const result = [ ] | ||
| for (let i=0; i < heap.length; i++) | ||
| result[i] = heap.arr[i].val | ||
| result[i] = heap.arr[i].item | ||
@@ -72,0 +161,0 @@ return result |
+12
-53
@@ -5,3 +5,3 @@ # priority-queue | ||
| [](https://travis-ci.org/mreinstein/priority-queue) | ||
|  | ||
@@ -27,11 +27,6 @@ | ||
| // declarea a custom function for comparing the priority values of 2 items in the queue | ||
| function comparator (a, b) { | ||
| return a < b ? true : false | ||
| } | ||
| // create a new priority queue that can hold a maximum of 20,000 items. | ||
| // by default max length is 1000 | ||
| const MAX_LENGTH = 20000 | ||
| const obj = PQ.create(comparator, MAX_LENGTH) | ||
| const obj = PQ.create(MAX_LENGTH) | ||
@@ -51,17 +46,5 @@ | ||
| console.log(PQ.dequeue(obj)) // undefined | ||
| ``` | ||
| By default dequeue will return the highest prioritied item in the queue first. | ||
| If you want to get the lowest priority item instead, pass a 3rd boolean argument: | ||
| ```javascript | ||
| const highest = PQ.dequeue(obj) | ||
| GET_HIGHEST = false | ||
| const lowest = PQ.dequeue(obj, GET_HIGHEST) | ||
| ``` | ||
| ## API | ||
@@ -76,28 +59,6 @@ | ||
| The Item stored in the queue should be class and a comparator should be provided. | ||
| ### Using classes/objects | ||
| ### If values in a queue are strings, comparator will receive priorities as a and b in the example below | ||
| We need max priority element to be removed first. | ||
| ```javascript | ||
| const comparator = function (a, b) { | ||
| return a >= b ? false : true | ||
| } | ||
| ``` | ||
| An example would be: | ||
| ```javascript | ||
| const obj = PriorityQueue.create(comparator) | ||
| PQ.queue(obj, 'c', 1) | ||
| PQ.queue(obj, 'b', 3) | ||
| PQ.queue(obj, 'a', 5) | ||
| console.log(PQ.dequeue(obj)) //'a' | ||
| ``` | ||
| ### If values in the queue is an object, comparator will receive the object and you need to compare priorities | ||
| ```javascript | ||
| class Box { | ||
@@ -107,21 +68,19 @@ constructor(w, l) { | ||
| this.l = l | ||
| this.area = w * l //this is priority | ||
| this.area = w * l // this is priority | ||
| } | ||
| comparator(a, b) { | ||
| return a.area >= b.area ? false : true | ||
| } | ||
| } | ||
| const obj = PQ.create(Box.prototype.comparator) | ||
| const obj = PQ.create() | ||
| const a = new Box(5, 5) | ||
| const b = new Box(9, 9) | ||
| PQ.queue(obj, a) | ||
| PQ.queue(obj, new Box(2, 3)) | ||
| PQ.queue(obj, new Box(3, 3)) | ||
| PQ.queue(obj, b) | ||
| const c = new Box(2, 3) | ||
| const d = new Box(3, 3) | ||
| PQ.queue(obj, a, a.area) | ||
| PQ.queue(obj, c, c.area) | ||
| PQ.queue(obj, d, d.area) | ||
| PQ.queue(obj, b, b.area) | ||
| assert.deepEqual(PQ.dequeue(obj), b) | ||
| assert.deepEqual(PQ.dequeue(obj), a) | ||
| ``` | ||
+101
-63
@@ -5,9 +5,2 @@ import PQ from './priority-queue.js' | ||
| // a is parent b is child | ||
| // sort in descending order | ||
| function comparator (a, b) { | ||
| return a < b ? true : false // swap true | ||
| } | ||
| // used for custom object testing | ||
@@ -20,13 +13,9 @@ class Box { | ||
| } | ||
| comparator(a, b) { | ||
| return a.area >= b.area ? false : true | ||
| } | ||
| } | ||
| describe('test', () => { | ||
| describe('test', () => { | ||
| it('basic test', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
| PQ.queue(obj, 'd', 1) | ||
@@ -37,6 +26,7 @@ PQ.queue(obj, 'a', 4) | ||
| assert.equal(PQ.dequeue(obj).val, 'a') | ||
| assert.equal(PQ.dequeue(obj).val, 'b') | ||
| assert.equal(PQ.dequeue(obj).val, 'c') | ||
| assert.equal(PQ.dequeue(obj).val, 'd') | ||
| assert.equal(PQ.dequeue(obj), 'a') | ||
| assert.equal(PQ.dequeue(obj), 'b') | ||
| assert.equal(PQ.dequeue(obj), 'c') | ||
| assert.equal(PQ.dequeue(obj), 'd') | ||
| assert.equal(PQ.dequeue(obj), undefined) | ||
@@ -46,9 +36,8 @@ }) | ||
| it('if queue is empty then dequeue undefined', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
| assert.equal(PQ.dequeue(obj), undefined) | ||
| }) | ||
| it('accepts 0 and negative numbers as valid values', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
@@ -59,10 +48,9 @@ PQ.queue(obj, -1, 1) | ||
| assert.equal(PQ.dequeue(obj).val, 0) | ||
| assert.equal(PQ.dequeue(obj).val, -5) | ||
| assert.equal(PQ.dequeue(obj).val, -1) | ||
| assert.equal(PQ.dequeue(obj), 0) | ||
| assert.equal(PQ.dequeue(obj), -5) | ||
| assert.equal(PQ.dequeue(obj), -1) | ||
| }) | ||
| it('re-prioritizes an existing element if it is in the queue', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
@@ -75,16 +63,20 @@ PQ.queue(obj, 'd', 1) | ||
| assert.equal(PQ.dequeue(obj).val, 'b') | ||
| assert.equal(PQ.dequeue(obj).val, 'a') | ||
| assert.equal(PQ.dequeue(obj).val, 'd') | ||
| assert.equal(PQ.dequeue(obj), 'b') | ||
| assert.equal(PQ.dequeue(obj), 'a') | ||
| assert.equal(PQ.dequeue(obj), 'd') | ||
| }) | ||
| it('throw an error if we try to queue with no priority', () => { | ||
| const obj = PQ.create() | ||
| assert.throws(() => { PQ.queue(obj, '3') }, /^Error/) | ||
| }) | ||
| it('throw an error if we try to delete a key that doesnt exist', () => { | ||
| const obj = PQ.create(comparator) | ||
| assert.throws(() => { PQ.delete(obj, '3') }, /^Error/) //delete key that doesnt exist | ||
| const obj = PQ.create() | ||
| assert.throws(() => { PQ.delete(obj, '3') }, /^Error/) // delete key that doesnt exist | ||
| }) | ||
| it('should delete before updating priority', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
| PQ.queue(obj, 'e', 3) | ||
@@ -96,9 +88,10 @@ PQ.queue(obj, 'b', 1) | ||
| PQ.queue(obj, 'a', 5) | ||
| assert.equal(PQ.dequeue(obj).val, 'a') | ||
| assert.equal(PQ.dequeue(obj).val, 'e') | ||
| assert.equal(PQ.dequeue(obj).val, 'b') | ||
| assert.equal(PQ.dequeue(obj), 'a') | ||
| assert.equal(PQ.dequeue(obj), 'e') | ||
| assert.equal(PQ.dequeue(obj), 'b') | ||
| }) | ||
| it('check if queue is empty', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
| assert.equal(PQ.isEmpty(obj), true) | ||
@@ -108,3 +101,3 @@ }) | ||
| it('clear the queue', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
| PQ.queue(obj, 'a', 5) | ||
@@ -117,3 +110,3 @@ assert.equal(PQ.isEmpty(obj), false) | ||
| it('list the contents of the queue', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
| PQ.queue(obj, 'c', 1) | ||
@@ -123,19 +116,16 @@ PQ.queue(obj, 'b', 3) | ||
| assert.equal(obj.length, 3) | ||
| assert.deepEqual(PQ.list(obj).slice(0, 3), [ { val: 'a', priority: 5 }, | ||
| { val: 'c', priority: 1 }, | ||
| { val: 'b', priority: 3 }]) | ||
| assert.deepEqual(PQ.list(obj).slice(0, 3), [ 'a', 'c', 'b' ]) | ||
| }) | ||
| it('should peek content of queue', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
| PQ.queue(obj, 'c', 1) | ||
| PQ.queue(obj, 'b', 3) | ||
| assert.deepEqual(PQ.peek(obj), { val:'b', priority: 3 }) | ||
| assert.deepEqual(PQ.peek(obj), 'b') | ||
| }) | ||
| describe('test with an object', () => { | ||
| it('basic test', () => { | ||
| const obj = PQ.create(Box.prototype.comparator) | ||
| const obj = PQ.create() | ||
| const a = new Box(5, 5) | ||
@@ -145,6 +135,6 @@ const b = new Box(2, 3) | ||
| const d = new Box(9, 9) | ||
| PQ.queue(obj, a) | ||
| PQ.queue(obj, b) | ||
| PQ.queue(obj, c) | ||
| PQ.queue(obj, d) | ||
| PQ.queue(obj, a, a.area) | ||
| PQ.queue(obj, b, b.area) | ||
| PQ.queue(obj, c, c.area) | ||
| PQ.queue(obj, d, d.area) | ||
@@ -159,29 +149,33 @@ assert.deepEqual(PQ.peek(obj), d) | ||
| it('test peek', () => { | ||
| const obj = PQ.create(Box.prototype.comparator) | ||
| PQ.queue(obj, new Box(5, 5)) | ||
| PQ.queue(obj, new Box(9, 9)) | ||
| const obj = PQ.create() | ||
| const a = new Box(5, 5) | ||
| const b = new Box(9, 9) | ||
| PQ.queue(obj, a, a.area) | ||
| PQ.queue(obj, b, b.area) | ||
| assert.deepEqual(PQ.peek(obj), new Box(9, 9)) | ||
| assert.deepEqual(PQ.peek(obj), b) | ||
| }) | ||
| it('throw an error if we try to add a duplicate element in queue', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
| const a = new Box(5, 5) | ||
| PQ.queue(obj, a) | ||
| PQ.queue(obj, a, a.area) | ||
| }) | ||
| it('throw an error if we try to delete a key that doesnt exist', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
| const a = new Box(15, 5) | ||
| PQ.queue(obj, a) | ||
| assert.throws(() => { PQ.delete(obj, new Box(15, 51)) }, /^Error/) //delete key that doesnt exist | ||
| PQ.queue(obj, a, a.area) | ||
| assert.throws(() => { PQ.delete(obj, new Box(15, 51)) }, /^Error/) // delete key that doesnt exist | ||
| }) | ||
| it('should delete before updating priority', () => { | ||
| const obj = PQ.create(comparator) | ||
| const obj = PQ.create() | ||
| const a = new Box(2, 3) | ||
| const b = new Box(5, 5) | ||
| const c = new Box(3, 3) | ||
| PQ.queue(obj, new Box(5, 5)) | ||
| PQ.queue(obj, a) | ||
| PQ.queue(obj, new Box(3, 3)) | ||
| PQ.queue(obj, b, b.area) | ||
| PQ.queue(obj, a, a.area) | ||
| PQ.queue(obj, c, c.area) | ||
| PQ.delete(obj, a) // so we delete | ||
@@ -191,7 +185,51 @@ | ||
| PQ.queue(obj, a) | ||
| PQ.queue(obj, a, a.area) | ||
| assert.deepEqual(PQ.list(obj)[2], a) | ||
| }) | ||
| it('should allow min-heap behavior with negative priority values', () => { | ||
| const obj = PQ.create() | ||
| // if we want to a min-heap (dequeue min value) we can do this by using negative signed priorities | ||
| const negate = (a) => -a | ||
| PQ.queue(obj, 'E', negate(0)) | ||
| PQ.queue(obj, 'A', negate(4)) | ||
| PQ.queue(obj, 'C', negate(1)) | ||
| PQ.queue(obj, 'B', negate(2)) | ||
| PQ.queue(obj, 'D', negate(0.34599)) | ||
| const output = [ ] | ||
| for (let i=0; i < 5; i++) | ||
| output.push(PQ.dequeue(obj)) | ||
| assert.deepEqual(output, [ 'E', 'D', 'C', 'B', 'A' ]) | ||
| }) | ||
| // https://github.com/mreinstein/priority-queue/issues/2 | ||
| it('should respect priority (gh issue #2)', () => { | ||
| const obj = PQ.create() | ||
| PQ.queue(obj, 'A', 0.9725668889004737) | ||
| PQ.queue(obj, 'C', 0.8222610668744892) | ||
| PQ.queue(obj, 'J', 0.12049612472765148) | ||
| PQ.queue(obj, 'B', 0.8349967401009053) | ||
| PQ.queue(obj, 'G', 0.3161299272906035) | ||
| PQ.queue(obj, 'F', 0.394229659345001) | ||
| PQ.queue(obj, 'D', 0.7465265986975282) | ||
| PQ.queue(obj, 'E', 0.6853948319330812) | ||
| PQ.queue(obj, 'I', 0.13059667288325727) | ||
| PQ.queue(obj, 'H', 0.14856508816592395) | ||
| const output = [ ] | ||
| for (let i=0; i < 10; i++) | ||
| output.push(PQ.dequeue(obj)) | ||
| assert.deepEqual(output, [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' ]) | ||
| }) | ||
| }) | ||
| }) |
| sudo: false | ||
| language: node_js | ||
| node_js: | ||
| - '14' | ||
| - '12' |
-92
| import removeItem from './remove-array-item.js' | ||
| // creates a new heap data structure | ||
| function create (comparator, maxLength=1000) { | ||
| if (!Number.isInteger(maxLength)) | ||
| throw new Error('maxLength must be an integer') | ||
| const arr = new Array(maxLength) | ||
| return { arr, length: 0, maxLength, comparator } | ||
| } | ||
| function insert (heap, item) { | ||
| if (heap.length === heap.maxLength) | ||
| return | ||
| heap.arr[heap.length] = item | ||
| heap.length++ | ||
| callHeapify(heap) | ||
| } | ||
| function callHeapify (heap) { | ||
| let ind = heap.length - 1 | ||
| while (ind > 0) { | ||
| if (ind % 2 === 0) | ||
| ind = (ind - 2) / 2 | ||
| else | ||
| ind = (ind - 1) / 2 | ||
| heapify(heap, ind) | ||
| } | ||
| } | ||
| function heapify (heap, parentInd) { | ||
| let largestInd = parentInd | ||
| const leftChildInd = 2 * parentInd + 1 | ||
| const rightChildInd = 2 * parentInd + 2 | ||
| // if child exists and is greater than parent | ||
| if (heap.length > leftChildInd && heap.comparator(getValue(heap.arr[parentInd]), getValue(heap.arr[leftChildInd]))) | ||
| largestInd = leftChildInd | ||
| if (heap.length > rightChildInd && heap.comparator(getValue(heap.arr[largestInd]), getValue(heap.arr[rightChildInd]))) | ||
| largestInd = rightChildInd | ||
| if (largestInd != parentInd) { | ||
| swap(heap, largestInd, parentInd) | ||
| heapify(heap, largestInd) | ||
| } | ||
| } | ||
| function poll (heap, dequeueHighest=true) { | ||
| if (heap.length === 0) | ||
| return | ||
| const max = dequeueHighest ? heap.arr[0] : heap.arr[heap.length-1] | ||
| if (dequeueHighest) | ||
| removeItem(heap.arr, heap.length, 0) | ||
| heap.length-- | ||
| callHeapify(heap) | ||
| return max.priority ? max : max.val | ||
| } | ||
| function peek (heap, dequeueHighest=true) { | ||
| if (heap.length === 0) | ||
| return | ||
| const firstIndex = dequeueHighest ? 0 : heap.length-1 | ||
| return heap.arr[firstIndex].priority ? heap.arr[firstIndex] : heap.arr[firstIndex].val | ||
| } | ||
| function getValue (obj) { | ||
| return obj.priority ? obj.priority : obj.val // if priority is undefined then return val | ||
| } | ||
| function swap (heap, i, j) { | ||
| const tmp = heap.arr[i] | ||
| heap.arr[i] = heap.arr[j] | ||
| heap.arr[j] = tmp | ||
| } | ||
| export default { create, callHeapify, insert, poll, peek } |
| /** | ||
| * Remove 1 item from an array | ||
| * | ||
| * @function removeItems | ||
| * @param {Array<*>} arr The target array | ||
| * @param {number} arrLength actual length of the array | ||
| * @param {number} removeIdx The index to remove from (inclusive) | ||
| */ | ||
| export default function removeItem (arr, arrLength, removeIdx) { | ||
| const len = arrLength - 1 | ||
| for (let i = removeIdx; i < len; ++i) | ||
| arr[i] = arr[i + 1] | ||
| } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
14852
9.94%308
14.93%1
-50%2
100%8
-11.11%82
-33.33%1
Infinity%