Skip to content

Commit 80cb097

Browse files
authored
[Issue #64] allow creating priority queues with initial list of values (#80)
1 parent e49d490 commit 80cb097

10 files changed

Lines changed: 191 additions & 386 deletions

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@
3636
"mocha": "^6.2.2"
3737
},
3838
"dependencies": {
39-
"@datastructures-js/heap": "^4.3.3"
39+
"@datastructures-js/heap": "^4.3.7"
4040
}
4141
}

src/maxPriorityQueue.d.ts

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
1-
import { MaxHeap, IGetCompareValue } from '@datastructures-js/heap';
1+
import { IGetCompareValue } from '@datastructures-js/heap';
2+
import { PriorityQueue } from './priorityQueue';
23
import { LegacyOptions } from './minPriorityQueue';
34

4-
export class MaxPriorityQueue<T> implements Iterable<T> {
5-
constructor(options?: IGetCompareValue<T> | LegacyOptions<T>, heap?: MaxHeap<T>);
6-
[Symbol.iterator](): Iterator<T, any, undefined>;
7-
size(): number;
8-
isEmpty(): boolean;
9-
front(): T | null;
10-
back(): T | null;
5+
export interface MaxPriorityQueue<T> extends PriorityQueue<T> {
116
enqueue(value: T): MaxPriorityQueue<T>;
127
push(value: T): MaxPriorityQueue<T>;
13-
dequeue(): T | null;
14-
pop(): T | null;
15-
remove(cb: (value: T) => boolean): T[];
16-
contains(cb: (value: T) => boolean): boolean;
17-
toArray(): T[];
18-
clear(): void;
19-
static fromArray<T>(values: T[], getCompareValue?: IGetCompareValue<T>): MaxPriorityQueue<T>;
208
}
9+
10+
export const MaxPriorityQueue: {
11+
new <T>(options?: IGetCompareValue<T> | LegacyOptions<T> | null | undefined, values?: T[]): MaxPriorityQueue<T>;
12+
fromArray<T>(values: T[], options?: IGetCompareValue<T> | LegacyOptions<T> | null | undefined): MaxPriorityQueue<T>;
13+
};

src/maxPriorityQueue.js

Lines changed: 25 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -3,60 +3,43 @@
33
* @license MIT
44
*/
55

6-
const { Heap, MaxHeap } = require('@datastructures-js/heap');
7-
8-
const getMaxCompare = (getCompareValue) => (a, b) => {
9-
const aVal = typeof getCompareValue === 'function' ? getCompareValue(a) : a;
10-
const bVal = typeof getCompareValue === 'function' ? getCompareValue(b) : b;
11-
return aVal < bVal ? 1 : -1;
12-
};
6+
const { PriorityQueue } = require('./priorityQueue');
137

148
/**
159
* @class MaxPriorityQueue
10+
* @extends PriorityQueue
1611
*/
17-
class MaxPriorityQueue {
18-
constructor(options, _heap) {
12+
class MaxPriorityQueue extends PriorityQueue {
13+
constructor(options, values) {
1914
// Handle legacy options format ({ compare: fn })
2015
if (options && typeof options === 'object' && typeof options.compare === 'function') {
21-
this._getCompareValue = null;
22-
const compareFunction = (a, b) => options.compare(a, b) >= 0 ? -1 : 1;
23-
this._heap = _heap || new Heap(compareFunction);
16+
const compareFunction = (a, b) => options.compare(a, b) <= 0 ? -1 : 1;
17+
super(compareFunction, values);
2418
} else {
2519
// Current format (direct compare function)
2620
const getCompareValue = options;
2721
if (getCompareValue && typeof getCompareValue !== 'function') {
2822
throw new Error('MaxPriorityQueue constructor requires a callback for object values');
2923
}
30-
this._heap = _heap || new MaxHeap(getCompareValue);
24+
// Create a MaxHeap-compatible compare function
25+
const compare = (a, b) => {
26+
const aVal = typeof getCompareValue === 'function' ? getCompareValue(a) : a;
27+
const bVal = typeof getCompareValue === 'function' ? getCompareValue(b) : b;
28+
return aVal < bVal ? 1 : -1;
29+
};
30+
super(compare, values);
3131
}
3232
}
3333

34-
/**
35-
* Returns an element with highest priority in the queue
36-
* @public
37-
* @returns {number|string|object}
38-
*/
39-
front() {
40-
return this._heap.root();
41-
}
42-
43-
/**
44-
* Returns an element with lowest priority in the queue
45-
* @public
46-
* @returns {number|string|object}
47-
*/
48-
back() {
49-
return this._heap.leaf();
50-
}
51-
5234
/**
5335
* Adds a value to the queue
5436
* @public
5537
* @param {number|string|object} value
5638
* @returns {MaxPriorityQueue}
5739
*/
5840
enqueue(value) {
59-
return this._heap.insert(value);
41+
super.enqueue(value);
42+
return this;
6043
}
6144

6245
/**
@@ -68,142 +51,16 @@ class MaxPriorityQueue {
6851
push(value) {
6952
return this.enqueue(value);
7053
}
71-
72-
/**
73-
* Removes and returns an element with highest priority in the queue
74-
* @public
75-
* @returns {number|string|object}
76-
*/
77-
dequeue() {
78-
return this._heap.extractRoot();
79-
}
80-
81-
/**
82-
* Removes and returns an element with highest priority in the queue
83-
* @public
84-
* @returns {number|string|object}
85-
*/
86-
pop() {
87-
return this.dequeue();
88-
}
89-
90-
/**
91-
* Removes all elements that match a criteria in the callback
92-
* @public
93-
* @param {function} cb
94-
* @returns {array}
95-
*/
96-
remove(cb) {
97-
if (typeof cb !== 'function') {
98-
throw new Error('MaxPriorityQueue remove expects a callback');
99-
}
100-
101-
const removed = [];
102-
const dequeued = [];
103-
while (!this.isEmpty()) {
104-
const popped = this.pop();
105-
if (cb(popped)) {
106-
removed.push(popped);
107-
} else {
108-
dequeued.push(popped);
109-
}
110-
}
111-
112-
dequeued.forEach((val) => this.push(val));
113-
return removed;
114-
}
115-
116-
/**
117-
* Checks if the queue contains an element that matches a criteria
118-
* @public
119-
* @param {function} cb
120-
* @returns {boolean}
121-
*/
122-
contains(cb) {
123-
if (typeof cb !== 'function') {
124-
throw new Error('MaxPriorityQueue contains expects a callback');
125-
}
126-
127-
let found = false;
128-
const dequeued = [];
129-
while (!this.isEmpty()) {
130-
const popped = this.pop();
131-
dequeued.push(popped);
132-
if (cb(popped)) {
133-
found = true;
134-
break;
135-
}
136-
}
137-
138-
dequeued.forEach((val) => this.push(val));
139-
return found;
140-
}
141-
142-
/**
143-
* Returns the number of elements in the queue
144-
* @public
145-
* @returns {number}
146-
*/
147-
size() {
148-
return this._heap.size();
149-
}
150-
151-
/**
152-
* Checks if the queue is empty
153-
* @public
154-
* @returns {boolean}
155-
*/
156-
isEmpty() {
157-
return this._heap.isEmpty();
158-
}
159-
160-
/**
161-
* Clears the queue
162-
* @public
163-
*/
164-
clear() {
165-
this._heap.clear();
166-
}
167-
168-
/**
169-
* Returns a sorted list of elements from highest to lowest priority
170-
* @public
171-
* @returns {array}
172-
*/
173-
toArray() {
174-
return this._heap.clone().sort().reverse();
175-
}
176-
177-
/**
178-
* Implements an iterable on the min priority queue
179-
* @public
180-
*/
181-
[Symbol.iterator]() {
182-
let size = this.size();
183-
return {
184-
next: () => {
185-
size -= 1;
186-
return {
187-
value: this.pop(),
188-
done: size === -1
189-
};
190-
}
191-
};
192-
}
193-
194-
/**
195-
* Creates a priority queue from an existing array
196-
* @public
197-
* @static
198-
* @returns {MaxPriorityQueue}
199-
*/
200-
static fromArray(values, getCompareValue) {
201-
const heap = new Heap(getMaxCompare(getCompareValue), values);
202-
return new MaxPriorityQueue(
203-
getCompareValue,
204-
new MaxHeap(getCompareValue, heap).fix()
205-
);
206-
}
20754
}
20855

56+
/**
57+
* Creates a priority queue from an existing array
58+
* @public
59+
* @static
60+
* @returns {MaxPriorityQueue}
61+
*/
62+
MaxPriorityQueue.fromArray = function fromArray(values, options) {
63+
return new MaxPriorityQueue(options, values);
64+
};
65+
20966
exports.MaxPriorityQueue = MaxPriorityQueue;

src/minPriorityQueue.d.ts

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
1-
import { MinHeap, IGetCompareValue } from '@datastructures-js/heap';
1+
import { IGetCompareValue } from '@datastructures-js/heap';
2+
import { PriorityQueue } from './priorityQueue';
23

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

7-
export class MinPriorityQueue<T> implements Iterable<T> {
8-
constructor(options?: IGetCompareValue<T> | LegacyOptions<T>, heap?: MinHeap<T>);
9-
[Symbol.iterator](): Iterator<T, any, undefined>;
10-
size(): number;
11-
isEmpty(): boolean;
12-
front(): T | null;
13-
back(): T | null;
8+
export interface MinPriorityQueue<T> extends PriorityQueue<T> {
149
enqueue(value: T): MinPriorityQueue<T>;
1510
push(value: T): MinPriorityQueue<T>;
16-
dequeue(): T | null;
17-
pop(): T | null;
18-
remove(cb: (value: T) => boolean): T[];
19-
contains(cb: (value: T) => boolean): boolean;
20-
toArray(): T[];
21-
clear(): void;
22-
static fromArray<T>(values: T[], getCompareValue?: IGetCompareValue<T>): MinPriorityQueue<T>;
2311
}
12+
13+
export const MinPriorityQueue: {
14+
new <T>(options?: IGetCompareValue<T> | LegacyOptions<T> | null | undefined, values?: T[]): MinPriorityQueue<T>;
15+
fromArray<T>(values: T[], options?: IGetCompareValue<T> | LegacyOptions<T> | null | undefined): MinPriorityQueue<T>;
16+
};

0 commit comments

Comments
 (0)