Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@
"mocha": "^6.2.2"
},
"dependencies": {
"@datastructures-js/heap": "^4.3.3"
"@datastructures-js/heap": "^4.3.7"
}
}
23 changes: 8 additions & 15 deletions src/maxPriorityQueue.d.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import { MaxHeap, IGetCompareValue } from '@datastructures-js/heap';
import { IGetCompareValue } from '@datastructures-js/heap';
import { PriorityQueue } from './priorityQueue';
import { LegacyOptions } from './minPriorityQueue';

export class MaxPriorityQueue<T> implements Iterable<T> {
constructor(options?: IGetCompareValue<T> | LegacyOptions<T>, heap?: MaxHeap<T>);
[Symbol.iterator](): Iterator<T, any, undefined>;
size(): number;
isEmpty(): boolean;
front(): T | null;
back(): T | null;
export interface MaxPriorityQueue<T> extends PriorityQueue<T> {
enqueue(value: T): MaxPriorityQueue<T>;
push(value: T): MaxPriorityQueue<T>;
dequeue(): T | null;
pop(): T | null;
remove(cb: (value: T) => boolean): T[];
contains(cb: (value: T) => boolean): boolean;
toArray(): T[];
clear(): void;
static fromArray<T>(values: T[], getCompareValue?: IGetCompareValue<T>): MaxPriorityQueue<T>;
}

export const MaxPriorityQueue: {
new <T>(options?: IGetCompareValue<T> | LegacyOptions<T> | null | undefined, values?: T[]): MaxPriorityQueue<T>;
fromArray<T>(values: T[], options?: IGetCompareValue<T> | LegacyOptions<T> | null | undefined): MaxPriorityQueue<T>;
};
193 changes: 25 additions & 168 deletions src/maxPriorityQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,43 @@
* @license MIT
*/

const { Heap, MaxHeap } = require('@datastructures-js/heap');

const getMaxCompare = (getCompareValue) => (a, b) => {
const aVal = typeof getCompareValue === 'function' ? getCompareValue(a) : a;
const bVal = typeof getCompareValue === 'function' ? getCompareValue(b) : b;
return aVal < bVal ? 1 : -1;
};
const { PriorityQueue } = require('./priorityQueue');

/**
* @class MaxPriorityQueue
* @extends PriorityQueue
*/
class MaxPriorityQueue {
constructor(options, _heap) {
class MaxPriorityQueue extends PriorityQueue {
constructor(options, values) {
// 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);
const compareFunction = (a, b) => options.compare(a, b) <= 0 ? -1 : 1;
super(compareFunction, values);
} 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);
// Create a MaxHeap-compatible compare function
const compare = (a, b) => {
const aVal = typeof getCompareValue === 'function' ? getCompareValue(a) : a;
const bVal = typeof getCompareValue === 'function' ? getCompareValue(b) : b;
return aVal < bVal ? 1 : -1;
};
super(compare, values);
}
}

/**
* Returns an element with highest priority in the queue
* @public
* @returns {number|string|object}
*/
front() {
return this._heap.root();
}

/**
* Returns an element with lowest priority in the queue
* @public
* @returns {number|string|object}
*/
back() {
return this._heap.leaf();
}

/**
* Adds a value to the queue
* @public
* @param {number|string|object} value
* @returns {MaxPriorityQueue}
*/
enqueue(value) {
return this._heap.insert(value);
super.enqueue(value);
return this;
}

/**
Expand All @@ -68,142 +51,16 @@ class MaxPriorityQueue {
push(value) {
return this.enqueue(value);
}

/**
* Removes and returns an element with highest priority in the queue
* @public
* @returns {number|string|object}
*/
dequeue() {
return this._heap.extractRoot();
}

/**
* Removes and returns an element with highest priority in the queue
* @public
* @returns {number|string|object}
*/
pop() {
return this.dequeue();
}

/**
* Removes all elements that match a criteria in the callback
* @public
* @param {function} cb
* @returns {array}
*/
remove(cb) {
if (typeof cb !== 'function') {
throw new Error('MaxPriorityQueue remove expects a callback');
}

const removed = [];
const dequeued = [];
while (!this.isEmpty()) {
const popped = this.pop();
if (cb(popped)) {
removed.push(popped);
} else {
dequeued.push(popped);
}
}

dequeued.forEach((val) => this.push(val));
return removed;
}

/**
* Checks if the queue contains an element that matches a criteria
* @public
* @param {function} cb
* @returns {boolean}
*/
contains(cb) {
if (typeof cb !== 'function') {
throw new Error('MaxPriorityQueue contains expects a callback');
}

let found = false;
const dequeued = [];
while (!this.isEmpty()) {
const popped = this.pop();
dequeued.push(popped);
if (cb(popped)) {
found = true;
break;
}
}

dequeued.forEach((val) => this.push(val));
return found;
}

/**
* Returns the number of elements in the queue
* @public
* @returns {number}
*/
size() {
return this._heap.size();
}

/**
* Checks if the queue is empty
* @public
* @returns {boolean}
*/
isEmpty() {
return this._heap.isEmpty();
}

/**
* Clears the queue
* @public
*/
clear() {
this._heap.clear();
}

/**
* Returns a sorted list of elements from highest to lowest priority
* @public
* @returns {array}
*/
toArray() {
return this._heap.clone().sort().reverse();
}

/**
* Implements an iterable on the min priority queue
* @public
*/
[Symbol.iterator]() {
let size = this.size();
return {
next: () => {
size -= 1;
return {
value: this.pop(),
done: size === -1
};
}
};
}

/**
* Creates a priority queue from an existing array
* @public
* @static
* @returns {MaxPriorityQueue}
*/
static fromArray(values, getCompareValue) {
const heap = new Heap(getMaxCompare(getCompareValue), values);
return new MaxPriorityQueue(
getCompareValue,
new MaxHeap(getCompareValue, heap).fix()
);
}
}

/**
* Creates a priority queue from an existing array
* @public
* @static
* @returns {MaxPriorityQueue}
*/
MaxPriorityQueue.fromArray = function fromArray(values, options) {
return new MaxPriorityQueue(options, values);
};

exports.MaxPriorityQueue = MaxPriorityQueue;
23 changes: 8 additions & 15 deletions src/minPriorityQueue.d.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import { MinHeap, IGetCompareValue } from '@datastructures-js/heap';
import { IGetCompareValue } from '@datastructures-js/heap';
import { PriorityQueue } from './priorityQueue';

export interface LegacyOptions<T> {
compare: (a: T, b: T) => number;
}

export class MinPriorityQueue<T> implements Iterable<T> {
constructor(options?: IGetCompareValue<T> | LegacyOptions<T>, heap?: MinHeap<T>);
[Symbol.iterator](): Iterator<T, any, undefined>;
size(): number;
isEmpty(): boolean;
front(): T | null;
back(): T | null;
export interface MinPriorityQueue<T> extends PriorityQueue<T> {
enqueue(value: T): MinPriorityQueue<T>;
push(value: T): MinPriorityQueue<T>;
dequeue(): T | null;
pop(): T | null;
remove(cb: (value: T) => boolean): T[];
contains(cb: (value: T) => boolean): boolean;
toArray(): T[];
clear(): void;
static fromArray<T>(values: T[], getCompareValue?: IGetCompareValue<T>): MinPriorityQueue<T>;
}

export const MinPriorityQueue: {
new <T>(options?: IGetCompareValue<T> | LegacyOptions<T> | null | undefined, values?: T[]): MinPriorityQueue<T>;
fromArray<T>(values: T[], options?: IGetCompareValue<T> | LegacyOptions<T> | null | undefined): MinPriorityQueue<T>;
};
Loading