diff --git a/.eslintrc b/.eslintrc index c4f8674..d34b21e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -4,6 +4,7 @@ "comma-dangle": ["error", { "functions": "ignore" }], + "no-confusing-arrow": 0, "no-underscore-dangle": [ "error", { "allowAfterThis": true } diff --git a/CHANGELOG.md b/CHANGELOG.md index 2752c66..9971c3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [6.3.3] - 2025-05-01 + +### Fixed +- Added backward compatibility with v5's compare function format for MinPriorityQueue and MaxPriorityQueue +- Fixed iterator type. + ## [6.3.2] - 2025-01-05 ### Fixed diff --git a/README.md b/README.md index 4bb6e3c..4b1b185 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A heap-based implementation of priority queue in javascript with typescript supp -# Contents (v6) +# Contents * [Install](#install) * [require](#require) * [import](#import) @@ -123,6 +123,19 @@ const numbersQueue = new MinPriorityQueue(); const bidsQueue = new MaxPriorityQueue((bid) => bid.value); ``` +##### Legacy Compare Function (v5 compatibility) +For backward compatibility with v5, you can also pass a compare function in an options object: + +```js +// MinPriorityQueue with legacy compare +const minQueue = new MinPriorityQueue({ compare: (a, b) => a - b }); + +// MaxPriorityQueue with legacy compare +const maxQueue = new MaxPriorityQueue({ compare: (a, b) => a - b }); +``` + +This format is supported for backward compatibility with v5 of the library. + ### fromArray If the queue is being created from an existing array, and there is no desire to use an extra O(n) space, this static function can turn an array into a priority queue in O(n) runtime. diff --git a/index.d.ts b/index.d.ts index e194f2d..fd211b0 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,5 +1,5 @@ import { PriorityQueue } from './src/priorityQueue'; -import { MinPriorityQueue } from './src/minPriorityQueue'; +import { MinPriorityQueue, LegacyOptions } from './src/minPriorityQueue'; import { MaxPriorityQueue } from './src/maxPriorityQueue'; import { ICompare, IGetCompareValue } from '@datastructures-js/heap'; @@ -8,3 +8,4 @@ export { MinPriorityQueue } export { MaxPriorityQueue } export { ICompare } export { IGetCompareValue } +export { LegacyOptions } diff --git a/package.json b/package.json index 956f55d..a64d4d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@datastructures-js/priority-queue", - "version": "6.3.2", + "version": "6.3.3", "description": "A heap-based implementation of priority queue in javascript with typescript support.", "main": "index.js", "types": "index.d.ts", diff --git a/src/maxPriorityQueue.d.ts b/src/maxPriorityQueue.d.ts index fd8db9c..8a8eae1 100644 --- a/src/maxPriorityQueue.d.ts +++ b/src/maxPriorityQueue.d.ts @@ -1,7 +1,8 @@ import { MaxHeap, IGetCompareValue } from '@datastructures-js/heap'; +import { LegacyOptions } from './minPriorityQueue'; export class MaxPriorityQueue implements Iterable { - constructor(getCompareValue?: IGetCompareValue, heap?: MaxHeap); + constructor(options?: IGetCompareValue | LegacyOptions, heap?: MaxHeap); [Symbol.iterator](): Iterator; size(): number; isEmpty(): boolean; diff --git a/src/maxPriorityQueue.js b/src/maxPriorityQueue.js index 1e64a8a..25471ff 100644 --- a/src/maxPriorityQueue.js +++ b/src/maxPriorityQueue.js @@ -13,14 +13,22 @@ const getMaxCompare = (getCompareValue) => (a, b) => { /** * @class MaxPriorityQueue - * @extends MaxHeap */ class MaxPriorityQueue { - constructor(getCompareValue, _heap) { - if (getCompareValue && typeof getCompareValue !== 'function') { - throw new Error('MaxPriorityQueue constructor requires a callback for object values'); + constructor(options, _heap) { + // Handle legacy options format ({ compare: fn }) + if (options && typeof options === 'object' && typeof options.compare === 'function') { + this._getCompareValue = null; + const compareFunction = (a, b) => options.compare(a, b) >= 0 ? -1 : 1; + this._heap = _heap || new Heap(compareFunction); + } else { + // Current format (direct compare function) + const getCompareValue = options; + if (getCompareValue && typeof getCompareValue !== 'function') { + throw new Error('MaxPriorityQueue constructor requires a callback for object values'); + } + this._heap = _heap || new MaxHeap(getCompareValue); } - this._heap = _heap || new MaxHeap(getCompareValue); } /** diff --git a/src/minPriorityQueue.d.ts b/src/minPriorityQueue.d.ts index 8f52bf9..ed6fc45 100644 --- a/src/minPriorityQueue.d.ts +++ b/src/minPriorityQueue.d.ts @@ -1,7 +1,11 @@ import { MinHeap, IGetCompareValue } from '@datastructures-js/heap'; +export interface LegacyOptions { + compare: (a: T, b: T) => number; +} + export class MinPriorityQueue implements Iterable { - constructor(getCompareValue?: IGetCompareValue, heap?: MinHeap); + constructor(options?: IGetCompareValue | LegacyOptions, heap?: MinHeap); [Symbol.iterator](): Iterator; size(): number; isEmpty(): boolean; diff --git a/src/minPriorityQueue.js b/src/minPriorityQueue.js index 1da0e99..116657c 100644 --- a/src/minPriorityQueue.js +++ b/src/minPriorityQueue.js @@ -15,11 +15,20 @@ const getMinCompare = (getCompareValue) => (a, b) => { * @class MinPriorityQueue */ class MinPriorityQueue { - constructor(getCompareValue, _heap) { - if (getCompareValue && typeof getCompareValue !== 'function') { - throw new Error('MinPriorityQueue constructor requires a callback for object values'); + constructor(options, _heap) { + // Handle legacy options format ({ compare: fn }) + if (options && typeof options === 'object' && typeof options.compare === 'function') { + this._getCompareValue = null; + const compareFunction = (a, b) => options.compare(a, b) <= 0 ? -1 : 1; + this._heap = _heap || new Heap(compareFunction); + } else { + // Current format (direct compare function) + const getCompareValue = options; + if (getCompareValue && typeof getCompareValue !== 'function') { + throw new Error('MinPriorityQueue constructor requires a callback for object values'); + } + this._heap = _heap || new MinHeap(getCompareValue); } - this._heap = _heap || new MinHeap(getCompareValue); } /** diff --git a/test/maxPriorityQueue.test.js b/test/maxPriorityQueue.test.js index 0ce101d..bd1d711 100644 --- a/test/maxPriorityQueue.test.js +++ b/test/maxPriorityQueue.test.js @@ -128,4 +128,20 @@ describe('MaxPriorityQueue', () => { }); }); }); + + describe('legacy compare function', () => { + const values = [50, 80, 30, 90, 60, 40, 20]; + const maxQ = new MaxPriorityQueue({ compare: (a, b) => a - b }); + + it('enqueue and dequeue with legacy compare', () => { + values.forEach((value) => maxQ.enqueue(value)); + expect(maxQ.dequeue()).to.equal(90); + expect(maxQ.dequeue()).to.equal(80); + expect(maxQ.dequeue()).to.equal(60); + expect(maxQ.dequeue()).to.equal(50); + expect(maxQ.dequeue()).to.equal(40); + expect(maxQ.dequeue()).to.equal(30); + expect(maxQ.dequeue()).to.equal(20); + }); + }); }); diff --git a/test/minPriorityQueue.test.js b/test/minPriorityQueue.test.js index 78b6b00..e4af573 100644 --- a/test/minPriorityQueue.test.js +++ b/test/minPriorityQueue.test.js @@ -125,4 +125,20 @@ describe('MinPriorityQueue', () => { }); }); + + describe('legacy compare function', () => { + const values = [50, 80, 30, 90, 60, 40, 20]; + const minQ = new MinPriorityQueue({ compare: (a, b) => a - b }); + + it('enqueue and dequeue with legacy compare', () => { + values.forEach((value) => minQ.enqueue(value)); + expect(minQ.dequeue()).to.equal(20); + expect(minQ.dequeue()).to.equal(30); + expect(minQ.dequeue()).to.equal(40); + expect(minQ.dequeue()).to.equal(50); + expect(minQ.dequeue()).to.equal(60); + expect(minQ.dequeue()).to.equal(80); + expect(minQ.dequeue()).to.equal(90); + }); + }); });