Skip to content

Commit

Permalink
[heap, priority queue] Redesigned tested pass
Browse files Browse the repository at this point in the history
  • Loading branch information
zrwusa committed Oct 15, 2023
1 parent 5fcd9fe commit c6177ff
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 167 deletions.
44 changes: 26 additions & 18 deletions test/unit/data-structures/heap/heap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,42 @@ describe('Heap Operation Test', () => {
});

it('should object heap work well', function () {
const minHeap = new MinHeap<{a: string}>();
minHeap.add(1, {a: 'a1'});
minHeap.add(6, {a: 'a6'});
minHeap.add(2, {a: 'a2'});
minHeap.add(0, {a: 'a0'});
const minHeap = new MinHeap<{a: string; key: number}>((a, b) => a.key - b.key);
minHeap.add({key: 1, a: 'a1'});
minHeap.add({key: 6, a: 'a6'});
minHeap.add({key: 2, a: 'a2'});
minHeap.add({key: 0, a: 'a0'});

expect(minHeap.peek()).toEqual({a: 'a0'});
expect(minHeap.toArray()).toEqual([{a: 'a0'}, {a: 'a1'}, {a: 'a2'}, {a: 'a6'}]);
expect(minHeap.peek()).toEqual({a: 'a0', key: 0});
console.log('---', minHeap.toArray());
expect(minHeap.toArray().map(item => ({a: item.a}))).toEqual([{a: 'a0'}, {a: 'a1'}, {a: 'a2'}, {a: 'a6'}]);
let i = 0;
const expectPolled = [{a: 'a0'}, {a: 'a1'}, {a: 'a2'}, {a: 'a6'}];
while (minHeap.size > 0) {
expect(minHeap.poll()).toEqual(expectPolled[i]);
expect({a: minHeap.poll()?.a}).toEqual(expectPolled[i]);
i++;
}

const maxHeap = new MaxHeap<{a: string}>();
maxHeap.add(1, {a: 'a1'});
maxHeap.add(6, {a: 'a6'});
maxHeap.add(5, {a: 'a5'});
maxHeap.add(2, {a: 'a2'});
maxHeap.add(0, {a: 'a0'});
maxHeap.add(9, {a: 'a9'});
expect(maxHeap.peek()).toEqual({a: 'a9'});
expect(maxHeap.toArray()).toEqual([{a: 'a9'}, {a: 'a2'}, {a: 'a6'}, {a: 'a1'}, {a: 'a0'}, {a: 'a5'}]);
const maxHeap = new MaxHeap<{key: number; a: string}>((a, b) => b.key - a.key);
maxHeap.add({key: 1, a: 'a1'});
maxHeap.add({key: 6, a: 'a6'});
maxHeap.add({key: 5, a: 'a5'});
maxHeap.add({key: 2, a: 'a2'});
maxHeap.add({key: 0, a: 'a0'});
maxHeap.add({key: 9, a: 'a9'});
expect(maxHeap.peek()).toEqual({a: 'a9', key: 9});
expect(maxHeap.toArray().map(item => ({a: item.a}))).toEqual([
{a: 'a9'},
{a: 'a2'},
{a: 'a6'},
{a: 'a1'},
{a: 'a0'},
{a: 'a5'}
]);
const maxExpectPolled = [{a: 'a9'}, {a: 'a6'}, {a: 'a5'}, {a: 'a2'}, {a: 'a1'}, {a: 'a0'}];
let maxI = 0;
while (maxHeap.size > 0) {
expect(maxHeap.poll()).toEqual(maxExpectPolled[maxI]);
expect({a: maxHeap.poll()?.a}).toEqual(maxExpectPolled[maxI]);
maxI++;
}
});
Expand Down
92 changes: 50 additions & 42 deletions test/unit/data-structures/heap/max-heap.test.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,52 @@
import {HeapItem, MaxHeap} from '../../../../src';

describe('MaxHeap Operation Test', () => {
it('should object Max Heap operations be proper', function () {
const maxHeap = new MaxHeap<{keyA: string}>();
const myObj1 = {keyA: 'a1'},
myObj6 = {keyA: 'a6'},
myObj5 = {keyA: 'a5'},
myObj2 = {keyA: 'a2'},
myObj0 = {keyA: 'a0'},
myObj9 = {keyA: 'a9'};
maxHeap.add(1, myObj1);
expect(maxHeap.has(myObj1)).toBe(true);
expect(maxHeap.has(myObj9)).toBe(false);
maxHeap.add(6, myObj6);
expect(maxHeap.has(myObj6)).toBe(true);
maxHeap.add(5, myObj5);
expect(maxHeap.has(myObj5)).toBe(true);
maxHeap.add(2, myObj2);
expect(maxHeap.has(myObj2)).toBe(true);
expect(maxHeap.has(myObj6)).toBe(true);
maxHeap.add(0, myObj0);
expect(maxHeap.has(myObj0)).toBe(true);
expect(maxHeap.has(myObj9)).toBe(false);
maxHeap.add(9, myObj9);
expect(maxHeap.has(myObj9)).toBe(true);

const peek9 = maxHeap.peek(true);
peek9 && peek9.val && expect(peek9.val.keyA).toBe('a9');

const heapToArr = maxHeap.toArray(true);
expect(heapToArr.map(item => item?.val?.keyA)).toEqual(['a9', 'a2', 'a6', 'a1', 'a0', 'a5']);

const values = ['a9', 'a6', 'a5', 'a2', 'a1', 'a0'];
let i = 0;
while (maxHeap.size > 0) {
const polled = maxHeap.poll(true);
expect(polled).toBeInstanceOf(HeapItem);
polled && expect(polled.val).toHaveProperty('keyA');
polled && polled.val && expect(polled.val.keyA).toBe(values[i]);
i++;
}
import {CompareFunction, MaxHeap} from '../../../../src';

describe('MaxHeap', () => {
const numberComparator: CompareFunction<number> = (a, b) => b - a;
let maxHeap: MaxHeap<number>;

beforeEach(() => {
maxHeap = new MaxHeap(numberComparator);
});

test('add and poll elements in descending order', () => {
maxHeap.add(3);
maxHeap.add(1);
maxHeap.add(4);
maxHeap.add(2);

expect(maxHeap.poll()).toBe(4);
expect(maxHeap.poll()).toBe(3);
expect(maxHeap.poll()).toBe(2);
expect(maxHeap.poll()).toBe(1);
});

test('peek at the top element without removing it', () => {
maxHeap.add(3);
maxHeap.add(1);
maxHeap.add(4);
maxHeap.add(2);

expect(maxHeap.peek()).toBe(4);
expect(maxHeap.size).toBe(4);
});

test('sort elements in descending order', () => {
maxHeap.add(3);
maxHeap.add(1);
maxHeap.add(4);
maxHeap.add(2);

const sortedArray = maxHeap.sort();
expect(sortedArray).toEqual([4, 3, 2, 1]);
});

test('check if the heap is empty', () => {
expect(maxHeap.isEmpty()).toBe(true);

maxHeap.add(5);
expect(maxHeap.isEmpty()).toBe(false);

maxHeap.poll();
expect(maxHeap.isEmpty()).toBe(true);
});
});
106 changes: 38 additions & 68 deletions test/unit/data-structures/heap/min-heap.test.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,52 @@
import {HeapItem, MinHeap} from '../../../../src';
import {CompareFunction, MinHeap} from '../../../../src';

describe('MinHeap Operation Test', () => {
it('should numeric Min Heap operations be proper', function () {
const minNumHeap = new MinHeap<number>();
expect(minNumHeap).toBeInstanceOf(MinHeap);
describe('MinHeap', () => {
const numberComparator: CompareFunction<number> = (a, b) => a - b;
let minHeap: MinHeap<number>;

minNumHeap.add(1);
expect(minNumHeap.has(1)).toBe(true);
minNumHeap.add(6);
expect(minNumHeap.has(2)).toBe(false);
expect(minNumHeap.has(6)).toBe(true);
minNumHeap.add(2);
expect(minNumHeap.has(2)).toBe(true);
minNumHeap.add(0);
expect(minNumHeap.has(0)).toBe(true);
minNumHeap.add(5);
expect(minNumHeap.has(5)).toBe(true);
minNumHeap.add(9);
expect(minNumHeap.has(9)).toBe(true);
expect(minNumHeap.size).toBe(6);

const poll1 = minNumHeap.poll(true);
expect(poll1).toBeInstanceOf(HeapItem);
poll1 instanceof HeapItem && expect(poll1.val).toBe(0);

const poll2 = minNumHeap.poll(true);
expect(poll2).toBeInstanceOf(HeapItem);
poll2 instanceof HeapItem && expect(poll2.val).toBe(1);
beforeEach(() => {
minHeap = new MinHeap(numberComparator);
});

const peek1 = minNumHeap.peek(true);
expect(peek1).toBeInstanceOf(HeapItem);
peek1 instanceof HeapItem && expect(peek1.val).toBe(2);
test('add and poll elements in ascending order', () => {
minHeap.add(3);
minHeap.add(1);
minHeap.add(4);
minHeap.add(2);

const heapArray = minNumHeap.toArray(true);
expect(heapArray).toBeInstanceOf(Array);
expect(heapArray.map(item => item?.priority)).toEqual([2, 5, 9, 6]);
expect(minNumHeap.size).toBe(4);
expect(minHeap.poll()).toBe(1);
expect(minHeap.poll()).toBe(2);
expect(minHeap.poll()).toBe(3);
expect(minHeap.poll()).toBe(4);
});

it('should object Min Heap operations be proper', function () {
class MyObject {
keyA: string;
test('peek at the top element without removing it', () => {
minHeap.add(3);
minHeap.add(1);
minHeap.add(4);
minHeap.add(2);

constructor(keyA: string) {
this.keyA = keyA;
}
}
expect(minHeap.peek()).toBe(1);
expect(minHeap.size).toBe(4);
});

const minObjHeap = new MinHeap<MyObject>();
test('sort elements in ascending order', () => {
minHeap.add(3);
minHeap.add(1);
minHeap.add(4);
minHeap.add(2);

const obj1 = new MyObject('a1'),
obj6 = new MyObject('a6'),
obj2 = new MyObject('a2'),
obj0 = new MyObject('a0');
minObjHeap.add(1, obj1);
expect(minObjHeap.has(obj1)).toBe(true);
expect(minObjHeap.has(obj6)).toBe(false);
minObjHeap.add(6, obj6);
expect(minObjHeap.has(obj6)).toBe(true);
minObjHeap.add(2, obj2);
expect(minObjHeap.has(obj2)).toBe(true);
minObjHeap.add(0, obj0);
expect(minObjHeap.has(obj0)).toBe(true);
const sortedArray = minHeap.sort();
expect(sortedArray).toEqual([1, 2, 3, 4]);
});

const peek = minObjHeap.peek(true);
peek && peek.val && expect(peek.val.keyA).toBe('a0');
test('check if the heap is empty', () => {
expect(minHeap.isEmpty()).toBe(true);

const heapToArr = minObjHeap.toArray(true);
expect(heapToArr.map(item => item?.val?.keyA)).toEqual(['a0', 'a1', 'a2', 'a6']);
minHeap.add(5);
expect(minHeap.isEmpty()).toBe(false);

const values = ['a0', 'a1', 'a2', 'a6'];
let i = 0;
while (minObjHeap.size > 0) {
const polled = minObjHeap.poll(true);
expect(polled).toBeInstanceOf(HeapItem);
polled && expect(polled.val).toBeInstanceOf(MyObject);
polled && polled.val && expect(polled.val.keyA).toBe(values[i]);
i++;
}
minHeap.poll();
expect(minHeap.isEmpty()).toBe(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@ describe('MaxPriorityQueue Operation Test', () => {
});

it('should add elements and maintain heap property in a object MaxPriorityQueue', () => {
const priorityQueue = new MaxPriorityQueue<{keyA: number}>({
nodes: [{keyA: 5}, {keyA: 3}, {keyA: 1}],
comparator: (a, b) => b.keyA - a.keyA
});

const priorityQueue = new MaxPriorityQueue<{keyA: number}>((a, b) => b.keyA - a.keyA);
priorityQueue.refill([{keyA: 5}, {keyA: 3}, {keyA: 1}]);
priorityQueue.add({keyA: 7});

expect(priorityQueue.poll()?.keyA).toBe(7);
Expand Down Expand Up @@ -56,7 +53,8 @@ describe('MaxPriorityQueue Operation Test', () => {

it('should correctly heapify an array', () => {
const array = [5, 3, 7, 1];
const heap = MaxPriorityQueue.heapify<number>({nodes: array});
const heap = MaxPriorityQueue.heapify<number>(array, (a, b) => b - a);
heap.refill(array);

expect(heap.poll()).toBe(7);
expect(heap.poll()).toBe(5);
Expand All @@ -66,7 +64,7 @@ describe('MaxPriorityQueue Operation Test', () => {

it('should correctly heapify an object array', () => {
const nodes = [{keyA: 5}, {keyA: 3}, {keyA: 7}, {keyA: 1}];
const maxPQ = MaxPriorityQueue.heapify<{keyA: number}>({nodes, comparator: (a, b) => b.keyA - a.keyA});
const maxPQ = MaxPriorityQueue.heapify<{keyA: number}>(nodes, (a, b) => b.keyA - a.keyA);

expect(maxPQ.poll()?.keyA).toBe(7);
expect(maxPQ.poll()?.keyA).toBe(5);
Expand All @@ -81,8 +79,8 @@ describe('MaxPriorityQueue Performance Test', () => {
new Set<number>(Array.from(new Array(magnitude.LINEAR), () => Math.floor(Math.random() * magnitude.LINEAR * 100)))
);
expect(nodes.length).toBeGreaterThan(magnitude.LINEAR / 2);
const maxPQ = new MaxPriorityQueue<number>({nodes});

const maxPQ = new MaxPriorityQueue<number>();
maxPQ.refill(nodes);
let prev = Number.MAX_SAFE_INTEGER;
const startTime = performance.now();
while (maxPQ.size > 0) {
Expand Down
44 changes: 14 additions & 30 deletions test/unit/data-structures/priority-queue/priority-queue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,37 @@ import {PriorityQueue} from '../../../../src';
import {getRandomInt} from '../../../utils';

describe('PriorityQueue Operation Test', () => {
it('should validate a priority queue', () => {
const minPQ = new PriorityQueue<number>({nodes: [1, 5, 7, 9, 3, 6, 2], comparator: (a, b) => a - b});

expect(minPQ.isValid()).toBe(true);
expect(PriorityQueue.isPriorityQueueified({nodes: minPQ.nodes, comparator: (a, b) => a - b})).toBe(true);
expect(PriorityQueue.isPriorityQueueified({nodes: minPQ.nodes, comparator: (a, b) => b - a})).toBe(false);
expect(
PriorityQueue.isPriorityQueueified({
nodes: [1, 5, 7, 9, 3, 6, 2],
comparator: (a, b) => b - a
})
).toBe(false);
});

it('should PriorityQueue poll, pee, heapify, toArray work well', function () {
const minPQ = new PriorityQueue<number>({nodes: [5, 2, 3, 4, 6, 1], comparator: (a, b) => a - b});
const minPQ = new PriorityQueue<number>((a, b) => a - b);
minPQ.refill([5, 2, 3, 4, 6, 1]);
expect(minPQ.toArray()).toEqual([1, 2, 3, 4, 6, 5]);
minPQ.poll();
minPQ.poll();
minPQ.poll();
expect(minPQ.toArray()).toEqual([4, 5, 6]);
expect(minPQ.peek()).toBe(4);
expect(
PriorityQueue.heapify({
nodes: [3, 2, 1, 5, 6, 7, 8, 9, 10],
comparator: (a, b) => a - b
}).toArray()
).toEqual([1, 2, 3, 5, 6, 7, 8, 9, 10]);
expect(PriorityQueue.heapify([3, 2, 1, 5, 6, 7, 8, 9, 10], (a, b) => a - b).toArray()).toEqual([
1, 2, 3, 5, 6, 7, 8, 9, 10
]);
});

it('should Max PriorityQueue poll, peek, heapify, toArray work well', function () {
const maxPriorityQueue = new PriorityQueue<number>({nodes: [5, 2, 3, 4, 6, 1], comparator: (a, b) => b - a});
const maxPriorityQueue = new PriorityQueue<number>((a, b) => b - a);
maxPriorityQueue.refill([5, 2, 3, 4, 6, 1]);
expect(maxPriorityQueue.toArray()).toEqual([6, 5, 3, 4, 2, 1]);
maxPriorityQueue.poll();
maxPriorityQueue.poll();
maxPriorityQueue.poll();
expect(maxPriorityQueue.toArray()).toEqual([3, 2, 1]);
expect(maxPriorityQueue.peek()).toBe(3);
expect(
PriorityQueue.heapify({
nodes: [3, 2, 1, 5, 6, 7, 8, 9, 10],
comparator: (a, b) => a - b
}).toArray()
).toEqual([1, 2, 3, 5, 6, 7, 8, 9, 10]);
expect(PriorityQueue.heapify([3, 2, 1, 5, 6, 7, 8, 9, 10], (a, b) => a - b).toArray()).toEqual([
1, 2, 3, 5, 6, 7, 8, 9, 10
]);
});

it('should PriorityQueue clone, sort, getNodes, dfs work well', function () {
const minPQ1 = new PriorityQueue<number>({nodes: [2, 5, 8, 3, 1, 6, 7, 4], comparator: (a, b) => a - b});
const minPQ1 = new PriorityQueue<number>((a, b) => a - b);
minPQ1.refill([2, 5, 8, 3, 1, 6, 7, 4]);
const clonedPriorityQueue = minPQ1.clone();
expect(clonedPriorityQueue.getNodes()).toEqual(minPQ1.getNodes());
expect(clonedPriorityQueue.sort()).toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
Expand All @@ -62,7 +45,8 @@ describe('PriorityQueue Operation Test', () => {
describe('Priority Queue Performance Test', () => {
it('should numeric heap work well', function () {
const values = Array.from(new Array(10000), () => getRandomInt(1, 10000000));
const minPriorityQueue = new PriorityQueue<number>({nodes: values, comparator: (a, b) => a - b});
const minPriorityQueue = new PriorityQueue<number>((a, b) => a - b);
minPriorityQueue.refill(values);
const sorted = minPriorityQueue.sort();
expect(sorted).toEqual(values.sort((a, b) => a - b));
});
Expand Down

0 comments on commit c6177ff

Please sign in to comment.