mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 04:44:04 +00:00
test: The test cases have been added, though slightly tricky. The overall test coverage is currently at 93.27%.
This commit is contained in:
parent
e6acc0f8f1
commit
07dd75de70
|
@ -163,8 +163,8 @@ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
|
|||
if (this.isEntry(rawEle)) {
|
||||
key = rawEle[0];
|
||||
value = rawEle[1];
|
||||
} else if (this.toEntryFn) {
|
||||
const item = this.toEntryFn(rawEle);
|
||||
} else if (this._toEntryFn) {
|
||||
const item = this._toEntryFn(rawEle);
|
||||
key = item[0];
|
||||
value = item[1];
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
|
|||
* @return A new hashmap with the same values as this one
|
||||
*/
|
||||
clone(): HashMap<K, V, R> {
|
||||
return new HashMap<K, V, R>(this, { hashFn: this.hashFn, toEntryFn: this.toEntryFn });
|
||||
return new HashMap<K, V, R>(this, { hashFn: this._hashFn, toEntryFn: this._toEntryFn });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -302,18 +302,6 @@ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
|
|||
return filteredMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* The put function sets a value in a data structure using a specified key.
|
||||
* @param {K} key - The key parameter is of type K, which represents the type of the key being passed
|
||||
* to the function.
|
||||
* @param {V} value - The value parameter represents the value that you want to associate with the
|
||||
* specified key in the data structure.
|
||||
* @returns The method is returning a boolean value.
|
||||
*/
|
||||
put(key: K, value: V): boolean {
|
||||
return this.set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The function returns an iterator that yields key-value pairs from both an object store and an
|
||||
* object map.
|
||||
|
@ -349,7 +337,7 @@ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
|
|||
|
||||
let strKey: string;
|
||||
if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {
|
||||
strKey = this.hashFn(key);
|
||||
strKey = this._hashFn(key);
|
||||
} else {
|
||||
if (keyType === 'number') {
|
||||
// TODO numeric key should has its own hash
|
||||
|
@ -379,7 +367,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
* @param [options] - The `options` parameter is an optional object that can contain the following
|
||||
* properties:
|
||||
*/
|
||||
constructor(entryOrRawElements: Iterable<R> = [], options?: LinkedHashMapOptions<K, V, R>) {
|
||||
constructor(entryOrRawElements: Iterable<R | [K, V]> = [], options?: LinkedHashMapOptions<K, V, R>) {
|
||||
super();
|
||||
this._sentinel = <HashMapLinkedNode<K, V>>{};
|
||||
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;
|
||||
|
@ -395,10 +383,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
}
|
||||
|
||||
if (entryOrRawElements) {
|
||||
for (const el of entryOrRawElements) {
|
||||
const [key, value] = this.toEntryFn(el);
|
||||
this.set(key, value);
|
||||
}
|
||||
this.setMany(entryOrRawElements);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -465,7 +450,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
return this._tail;
|
||||
}
|
||||
|
||||
protected _toEntryFn: (rawElement: R) => [K, V] = (rawElement: R) => {
|
||||
protected _toEntryFn?: (rawElement: R) => [K, V] = (rawElement: R) => {
|
||||
if (this.isEntry(rawElement)) {
|
||||
// TODO, For performance optimization, it may be necessary to only inspect the first element traversed.
|
||||
return rawElement;
|
||||
|
@ -575,7 +560,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
const isNewKey = !this.has(key); // Check if the key is new
|
||||
|
||||
if (isWeakKey(key)) {
|
||||
const hash = this.objHashFn(key);
|
||||
const hash = this._objHashFn(key);
|
||||
node = this.objMap.get(hash);
|
||||
|
||||
if (!node && isNewKey) {
|
||||
|
@ -587,7 +572,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
node.value = value;
|
||||
}
|
||||
} else {
|
||||
const hash = this.hashFn(key);
|
||||
const hash = this._hashFn(key);
|
||||
node = this.noObjMap[hash];
|
||||
|
||||
if (!node && isNewKey) {
|
||||
|
@ -623,11 +608,20 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
* R.
|
||||
* @returns The `setMany` function returns an array of booleans.
|
||||
*/
|
||||
setMany(entryOrRawElements: Iterable<R>): boolean[] {
|
||||
setMany(entryOrRawElements: Iterable<R | [K, V]>): boolean[] {
|
||||
const results: boolean[] = [];
|
||||
for (const rawEle of entryOrRawElements) {
|
||||
const [key, value] = this.toEntryFn(rawEle);
|
||||
results.push(this.set(key, value));
|
||||
let key: K | undefined, value: V | undefined;
|
||||
if (this.isEntry(rawEle)) {
|
||||
key = rawEle[0];
|
||||
value = rawEle[1];
|
||||
} else if (this._toEntryFn) {
|
||||
const item = this._toEntryFn(rawEle);
|
||||
key = item[0];
|
||||
value = item[1];
|
||||
}
|
||||
|
||||
if (key !== undefined && value !== undefined) results.push(this.set(key, value));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -640,10 +634,10 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
*/
|
||||
override has(key: K): boolean {
|
||||
if (isWeakKey(key)) {
|
||||
const hash = this.objHashFn(key);
|
||||
const hash = this._objHashFn(key);
|
||||
return this.objMap.has(hash);
|
||||
} else {
|
||||
const hash = this.hashFn(key);
|
||||
const hash = this._hashFn(key);
|
||||
return hash in this.noObjMap;
|
||||
}
|
||||
}
|
||||
|
@ -668,11 +662,11 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
*/
|
||||
override get(key: K): V | undefined {
|
||||
if (isWeakKey(key)) {
|
||||
const hash = this.objHashFn(key);
|
||||
const hash = this._objHashFn(key);
|
||||
const node = this.objMap.get(hash);
|
||||
return node ? node.value : undefined;
|
||||
} else {
|
||||
const hash = this.hashFn(key);
|
||||
const hash = this._hashFn(key);
|
||||
const node = this.noObjMap[hash];
|
||||
return node ? node.value : undefined;
|
||||
}
|
||||
|
@ -722,7 +716,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
let node;
|
||||
|
||||
if (isWeakKey(key)) {
|
||||
const hash = this.objHashFn(key);
|
||||
const hash = this._objHashFn(key);
|
||||
// Get nodes from WeakMap
|
||||
node = this.objMap.get(hash);
|
||||
|
||||
|
@ -733,7 +727,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
// Remove nodes from WeakMap
|
||||
this.objMap.delete(hash);
|
||||
} else {
|
||||
const hash = this.hashFn(key);
|
||||
const hash = this._hashFn(key);
|
||||
// Get nodes from noObjMap
|
||||
node = this.noObjMap[hash];
|
||||
|
||||
|
@ -832,7 +826,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
* of the original `LinkedHashMap` object.
|
||||
*/
|
||||
clone(): LinkedHashMap<K, V> {
|
||||
const cloned = new LinkedHashMap<K, V>([], { hashFn: this.hashFn, objHashFn: this.objHashFn });
|
||||
const cloned = new LinkedHashMap<K, V>([], { hashFn: this._hashFn, objHashFn: this._objHashFn });
|
||||
for (const entry of this) {
|
||||
const [key, value] = entry;
|
||||
cloned.set(key, value);
|
||||
|
@ -905,26 +899,6 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
|
|||
return mappedMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The put function sets a value in a data structure using a specified key.
|
||||
* @param {K} key - The key parameter is of type K, which represents the type of the key being passed
|
||||
* to the function.
|
||||
* @param {V} value - The value parameter represents the value that you want to associate with the
|
||||
* specified key in the data structure.
|
||||
* @returns The method is returning a boolean value.
|
||||
*/
|
||||
put(key: K, value: V): boolean {
|
||||
return this.set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
|
|
@ -350,7 +350,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
* successfully deleted from the linked list, and `false` if the value or node is not found in the linked list.
|
||||
*/
|
||||
delete(valueOrNode: E | SinglyLinkedListNode<E> | undefined): boolean {
|
||||
if (!valueOrNode) return false;
|
||||
if (valueOrNode === undefined) return false;
|
||||
let value: E;
|
||||
if (valueOrNode instanceof SinglyLinkedListNode) {
|
||||
value = valueOrNode.value;
|
||||
|
|
|
@ -507,7 +507,6 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
cutRest(pos: number, isCutSelf = false): Deque<E> {
|
||||
if (isCutSelf) {
|
||||
if (pos < 0) {
|
||||
this.clear();
|
||||
return this;
|
||||
}
|
||||
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
|
||||
|
@ -517,7 +516,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
return this;
|
||||
} else {
|
||||
const newDeque = new Deque<E>([], { bucketSize: this._bucketSize });
|
||||
|
||||
if (pos < 0) pos = 0;
|
||||
for (let i = pos; i < this.size; i++) {
|
||||
newDeque.push(this.at(i));
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E,
|
|||
return this.size > 0 ? this.elements[this.elements.length - 1] : undefined;
|
||||
}
|
||||
|
||||
_autoCompactRatio: number = 0.5;
|
||||
protected _autoCompactRatio: number = 0.5;
|
||||
|
||||
/**
|
||||
* This function returns the value of the autoCompactRatio property.
|
||||
|
|
|
@ -12,7 +12,6 @@ export class TreeNode<V = any> {
|
|||
constructor(key: string, value?: V, children?: TreeNode<V>[]) {
|
||||
this._key = key;
|
||||
this._value = value || undefined;
|
||||
this._children = children || [];
|
||||
}
|
||||
|
||||
protected _key: string;
|
||||
|
|
|
@ -617,14 +617,14 @@ describe('AVLTreeMultiMap iterative methods test', () => {
|
|||
treeMM.add([3, 'c'], undefined, 1);
|
||||
});
|
||||
|
||||
test('The node obtained by get Node should match the node type', () => {
|
||||
it('The node obtained by get Node should match the node type', () => {
|
||||
const node3 = treeMM.getNode(3);
|
||||
expect(node3).toBeInstanceOf(BinaryTreeNode);
|
||||
expect(node3).toBeInstanceOf(BSTNode);
|
||||
expect(node3).toBeInstanceOf(AVLTreeNode);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
it('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
treeMM.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
|
@ -636,7 +636,7 @@ describe('AVLTreeMultiMap iterative methods test', () => {
|
|||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
it('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = treeMM.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([
|
||||
|
@ -645,7 +645,7 @@ describe('AVLTreeMultiMap iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
it('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = treeMM.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([
|
||||
|
@ -655,12 +655,12 @@ describe('AVLTreeMultiMap iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
it('reduce should accumulate values', () => {
|
||||
const sum = treeMM.reduce((acc, value, key) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should provide an iterator', () => {
|
||||
it('[Symbol.iterator] should provide an iterator', () => {
|
||||
const entries = [];
|
||||
for (const entry of treeMM) {
|
||||
entries.push(entry);
|
||||
|
@ -674,19 +674,19 @@ describe('AVLTreeMultiMap iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should clone work well', () => {
|
||||
it('should clone work well', () => {
|
||||
expect(treeMM.count).toBe(21);
|
||||
const cloned = treeMM.clone();
|
||||
expect(cloned.root?.left?.key).toBe(1);
|
||||
expect(cloned.root?.right?.value).toBe('c');
|
||||
});
|
||||
|
||||
test('should keys', () => {
|
||||
it('should keys', () => {
|
||||
const keys = treeMM.keys();
|
||||
expect([...keys]).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('should values', () => {
|
||||
it('should values', () => {
|
||||
const values = treeMM.values();
|
||||
expect([...values]).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
|
|
|
@ -339,14 +339,14 @@ describe('AVLTree iterative methods test', () => {
|
|||
avl.add([3, 'c']);
|
||||
});
|
||||
|
||||
test('The node obtained by get Node should match the node type', () => {
|
||||
it('The node obtained by get Node should match the node type', () => {
|
||||
const node3 = avl.getNode(3);
|
||||
expect(node3).toBeInstanceOf(BinaryTreeNode);
|
||||
expect(node3).toBeInstanceOf(BSTNode);
|
||||
expect(node3).toBeInstanceOf(AVLTreeNode);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
it('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
avl.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
|
@ -358,7 +358,7 @@ describe('AVLTree iterative methods test', () => {
|
|||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
it('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = avl.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([
|
||||
|
@ -367,7 +367,7 @@ describe('AVLTree iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
it('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = avl.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([
|
||||
|
@ -377,12 +377,12 @@ describe('AVLTree iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
it('reduce should accumulate values', () => {
|
||||
const sum = avl.reduce((acc, value, key) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should provide an iterator', () => {
|
||||
it('[Symbol.iterator] should provide an iterator', () => {
|
||||
const entries = [];
|
||||
for (const entry of avl) {
|
||||
entries.push(entry);
|
||||
|
@ -396,18 +396,18 @@ describe('AVLTree iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should clone work well', () => {
|
||||
it('should clone work well', () => {
|
||||
const cloned = avl.clone();
|
||||
expect(cloned.root?.left?.key).toBe(1);
|
||||
expect(cloned.root?.right?.value).toBe('c');
|
||||
});
|
||||
|
||||
test('should keys', () => {
|
||||
it('should keys', () => {
|
||||
const keys = avl.keys();
|
||||
expect([...keys]).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('should values', () => {
|
||||
it('should values', () => {
|
||||
const values = avl.values();
|
||||
expect([...values]).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
|
|
|
@ -767,12 +767,12 @@ describe('BinaryTree iterative methods test', () => {
|
|||
binaryTree.add([3, 'c']);
|
||||
});
|
||||
|
||||
test('The node obtained by get Node should match the node type', () => {
|
||||
it('The node obtained by get Node should match the node type', () => {
|
||||
const node3 = binaryTree.getNode(3);
|
||||
expect(node3).toBeInstanceOf(BinaryTreeNode);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
it('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
binaryTree.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
|
@ -784,7 +784,7 @@ describe('BinaryTree iterative methods test', () => {
|
|||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
it('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = binaryTree.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([
|
||||
|
@ -793,7 +793,7 @@ describe('BinaryTree iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
it('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = binaryTree.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([
|
||||
|
@ -803,12 +803,12 @@ describe('BinaryTree iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
it('reduce should accumulate values', () => {
|
||||
const sum = binaryTree.reduce((acc, currentValue, currentKey) => acc + currentKey, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should provide an iterator', () => {
|
||||
it('[Symbol.iterator] should provide an iterator', () => {
|
||||
const entries = [];
|
||||
for (const entry of binaryTree) {
|
||||
entries.push(entry);
|
||||
|
@ -822,23 +822,23 @@ describe('BinaryTree iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should clone work well', () => {
|
||||
it('should clone work well', () => {
|
||||
const cloned = binaryTree.clone();
|
||||
expect(cloned.root?.left?.key).toBe(2);
|
||||
expect(cloned.root?.right?.value).toBe('c');
|
||||
});
|
||||
|
||||
test('should keys', () => {
|
||||
it('should keys', () => {
|
||||
const keys = binaryTree.keys();
|
||||
expect([...keys]).toEqual([2, 1, 3]);
|
||||
});
|
||||
|
||||
test('should values', () => {
|
||||
it('should values', () => {
|
||||
const values = binaryTree.values();
|
||||
expect([...values]).toEqual(['b', 'a', 'c']);
|
||||
});
|
||||
|
||||
test('should iterative method return undefined when the node is null', () => {
|
||||
it('should iterative method return undefined when the node is null', () => {
|
||||
const tree = new BinaryTree();
|
||||
tree.addMany([-10, -10, -10, 9, 9, 20, null, null, 15, 7, 8, null, 2, null, 6, null, null, 8, 8, 8]);
|
||||
const bfsResult = tree.bfs(undefined, undefined, undefined, true);
|
||||
|
|
|
@ -873,13 +873,13 @@ describe('BST operations test recursively', () => {
|
|||
});
|
||||
|
||||
describe('BST isBST', function () {
|
||||
test('isBST', () => {
|
||||
it('isBST', () => {
|
||||
const bst = new BST<number, number>();
|
||||
bst.addMany([1, 2, 3, 9, 8, 5, 6, 7, 4]);
|
||||
expect(bst.isBST()).toBe(true);
|
||||
});
|
||||
|
||||
test('isBST when variant is Max', () => {
|
||||
it('isBST when variant is Max', () => {
|
||||
const bst = new BST<number, number>([1, 2, 3, 9, 8, 5, 6, 7, 4], {
|
||||
comparator: (a, b) => b - a
|
||||
});
|
||||
|
@ -961,13 +961,13 @@ describe('BST iterative methods test', () => {
|
|||
bst.add([3, 'c']);
|
||||
});
|
||||
|
||||
test('The node obtained by get Node should match the node type', () => {
|
||||
it('The node obtained by get Node should match the node type', () => {
|
||||
const node3 = bst.getNode(3);
|
||||
expect(node3).toBeInstanceOf(BinaryTreeNode);
|
||||
expect(node3).toBeInstanceOf(BSTNode);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
it('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
bst.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
|
@ -979,7 +979,7 @@ describe('BST iterative methods test', () => {
|
|||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
it('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = bst.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([
|
||||
|
@ -988,7 +988,7 @@ describe('BST iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
it('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = bst.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([
|
||||
|
@ -998,12 +998,12 @@ describe('BST iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
it('reduce should accumulate values', () => {
|
||||
const sum = bst.reduce((acc, value, key) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should provide an iterator', () => {
|
||||
it('[Symbol.iterator] should provide an iterator', () => {
|
||||
const entries = [];
|
||||
for (const entry of bst) {
|
||||
entries.push(entry);
|
||||
|
@ -1017,18 +1017,18 @@ describe('BST iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should clone work well', () => {
|
||||
it('should clone work well', () => {
|
||||
const cloned = bst.clone();
|
||||
expect(cloned.root?.left).toBe(undefined);
|
||||
expect(cloned.root?.right?.value).toBe('b');
|
||||
});
|
||||
|
||||
test('should keys', () => {
|
||||
it('should keys', () => {
|
||||
const keys = bst.keys();
|
||||
expect([...keys]).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('should values', () => {
|
||||
it('should values', () => {
|
||||
const values = bst.values();
|
||||
expect([...values]).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
|
|
|
@ -619,14 +619,14 @@ describe('RedBlackTree 2', () => {
|
|||
rbTree.add([3, 'c']);
|
||||
});
|
||||
|
||||
test('The node obtained by get Node should match the node type', () => {
|
||||
it('The node obtained by get Node should match the node type', () => {
|
||||
const node3 = rbTree.getNode(3);
|
||||
expect(node3).toBeInstanceOf(BinaryTreeNode);
|
||||
expect(node3).toBeInstanceOf(BSTNode);
|
||||
expect(node3).toBeInstanceOf(RedBlackTreeNode);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
it('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
rbTree.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
|
@ -638,7 +638,7 @@ describe('RedBlackTree 2', () => {
|
|||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new rbTree with filtered elements', () => {
|
||||
it('filter should return a new rbTree with filtered elements', () => {
|
||||
const filteredTree = rbTree.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([
|
||||
|
@ -647,7 +647,7 @@ describe('RedBlackTree 2', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('map should return a new rbTree with modified elements', () => {
|
||||
it('map should return a new rbTree with modified elements', () => {
|
||||
const mappedTree = rbTree.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([
|
||||
|
@ -657,12 +657,12 @@ describe('RedBlackTree 2', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
it('reduce should accumulate values', () => {
|
||||
const sum = rbTree.reduce((acc, value, key) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should provide an iterator', () => {
|
||||
it('[Symbol.iterator] should provide an iterator', () => {
|
||||
const entries = [];
|
||||
for (const entry of rbTree) {
|
||||
entries.push(entry);
|
||||
|
|
|
@ -755,14 +755,14 @@ describe('TreeMultiMap iterative methods test', () => {
|
|||
treeMM.add([3, 'c'], undefined, 1);
|
||||
});
|
||||
|
||||
test('The node obtained by get Node should match the node type', () => {
|
||||
it('The node obtained by get Node should match the node type', () => {
|
||||
const node3 = treeMM.getNode(3);
|
||||
expect(node3).toBeInstanceOf(BinaryTreeNode);
|
||||
expect(node3).toBeInstanceOf(BSTNode);
|
||||
expect(node3).toBeInstanceOf(RedBlackTreeNode);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
it('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
treeMM.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
|
@ -774,7 +774,7 @@ describe('TreeMultiMap iterative methods test', () => {
|
|||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
it('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = treeMM.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([
|
||||
|
@ -783,7 +783,7 @@ describe('TreeMultiMap iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
it('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = treeMM.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([
|
||||
|
@ -793,12 +793,12 @@ describe('TreeMultiMap iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
it('reduce should accumulate values', () => {
|
||||
const sum = treeMM.reduce((acc, value, key) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should provide an iterator', () => {
|
||||
it('[Symbol.iterator] should provide an iterator', () => {
|
||||
const entries = [];
|
||||
for (const entry of treeMM) {
|
||||
entries.push(entry);
|
||||
|
@ -812,7 +812,7 @@ describe('TreeMultiMap iterative methods test', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should clone work well', () => {
|
||||
it('should clone work well', () => {
|
||||
expect(treeMM.count).toBe(21);
|
||||
expect(treeMM.getComputedCount()).toBe(21);
|
||||
const cloned = treeMM.clone();
|
||||
|
@ -820,12 +820,12 @@ describe('TreeMultiMap iterative methods test', () => {
|
|||
expect(cloned.root?.right?.value).toBe('c');
|
||||
});
|
||||
|
||||
test('should keys', () => {
|
||||
it('should keys', () => {
|
||||
const keys = treeMM.keys();
|
||||
expect([...keys]).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('should values', () => {
|
||||
it('should values', () => {
|
||||
const values = treeMM.values();
|
||||
expect([...values]).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
|
|
|
@ -139,14 +139,6 @@ class MyDirectedGraph<
|
|||
override createEdge(src: VertexKey, dest: VertexKey, weight?: number, value?: E): EO {
|
||||
return new MyEdge(src, dest, weight ?? 1, value) as EO;
|
||||
}
|
||||
|
||||
setInEdgeMap(value: Map<VO, EO[]>) {
|
||||
this._inEdgeMap = value;
|
||||
}
|
||||
|
||||
setOutEdgeMap(value: Map<VO, EO[]>) {
|
||||
this._outEdgeMap = value;
|
||||
}
|
||||
}
|
||||
|
||||
describe('Inherit from DirectedGraph and perform operations', () => {
|
||||
|
@ -172,8 +164,8 @@ describe('Inherit from DirectedGraph and perform operations', () => {
|
|||
myGraph.addVertex(2, 'data2');
|
||||
myGraph.addEdge(1, 2, 10, 'edge-data1-2');
|
||||
myGraph.addEdge(new MyEdge(2, 1, 20, 'edge-data2-1'));
|
||||
myGraph.setInEdgeMap(myGraph.inEdgeMap);
|
||||
myGraph.setOutEdgeMap(myGraph.outEdgeMap);
|
||||
myGraph.inEdgeMap = myGraph.inEdgeMap;
|
||||
myGraph.outEdgeMap = myGraph.outEdgeMap;
|
||||
|
||||
expect(myGraph.edgeSet().length).toBe(2);
|
||||
// TODO
|
||||
|
@ -205,11 +197,14 @@ describe('Inherit from DirectedGraph and perform operations', () => {
|
|||
});
|
||||
|
||||
it('Remove edge between vertexMap', () => {
|
||||
expect(myGraph.isEmpty()).toBe(true);
|
||||
myGraph.addVertex(1, 'data1');
|
||||
myGraph.addVertex(2, 'data2');
|
||||
myGraph.addEdge(1, 2, 10, 'edge-data1-2');
|
||||
expect(myGraph.isEmpty()).toBe(false);
|
||||
|
||||
const removedEdge = myGraph.deleteEdgeSrcToDest(1, 2);
|
||||
expect(myGraph.deleteEdgeSrcToDest(2, 10)).toBe(undefined);
|
||||
const edgeAfterRemoval = myGraph.getEdge(1, 2);
|
||||
|
||||
expect(removedEdge).toBeInstanceOf(MyEdge);
|
||||
|
@ -220,6 +215,25 @@ describe('Inherit from DirectedGraph and perform operations', () => {
|
|||
expect(edgeAfterRemoval).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should clear', () => {
|
||||
expect(myGraph.isEmpty()).toBe(true);
|
||||
myGraph.addVertex(1, 'data1');
|
||||
myGraph.addVertex(2, 'data2');
|
||||
myGraph.addEdge(1, 2, 10, 'edge-data1-2');
|
||||
expect(myGraph.isEmpty()).toBe(false);
|
||||
myGraph.clear();
|
||||
expect(myGraph.isEmpty()).toBe(true);
|
||||
});
|
||||
|
||||
it('should clone', () => {
|
||||
myGraph.addVertex(1, 'data1');
|
||||
myGraph.addVertex(2, 'data2');
|
||||
myGraph.addEdge(1, 2, 10, 'edge-data1-2');
|
||||
const cloned = myGraph.clone();
|
||||
expect(cloned.hasVertex(1)).toBe(true);
|
||||
expect(cloned.hasEdge(1, 2)).toBe(true);
|
||||
});
|
||||
|
||||
it('Topological sort', () => {
|
||||
const sorted = myGraph.topologicalSort();
|
||||
|
||||
|
@ -656,7 +670,7 @@ describe('DirectedGraph iterative Methods', () => {
|
|||
vertexMap.forEach(vertex => graph.addVertex(vertex));
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should iterate over all vertexMap', () => {
|
||||
it('[Symbol.iterator] should iterate over all vertexMap', () => {
|
||||
const iteratedVertices = [];
|
||||
for (const vertex of graph) {
|
||||
iteratedVertices.push(vertex[0]);
|
||||
|
@ -664,13 +678,13 @@ describe('DirectedGraph iterative Methods', () => {
|
|||
expect(iteratedVertices).toEqual(vertexMap);
|
||||
});
|
||||
|
||||
test('forEach should apply a function to each vertex', () => {
|
||||
it('forEach should apply a function to each vertex', () => {
|
||||
const result: VertexKey[] = [];
|
||||
graph.forEach((value, key) => key && result.push(key));
|
||||
expect(result).toEqual(vertexMap);
|
||||
});
|
||||
|
||||
test('filter should return vertexMap that satisfy the condition', () => {
|
||||
it('filter should return vertexMap that satisfy the condition', () => {
|
||||
const filtered = graph.filter((value, vertex) => vertex === 'A' || vertex === 'B');
|
||||
expect(filtered).toEqual([
|
||||
['A', undefined],
|
||||
|
@ -678,17 +692,17 @@ describe('DirectedGraph iterative Methods', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('map should apply a function to each vertex and return a new array', () => {
|
||||
it('map should apply a function to each vertex and return a new array', () => {
|
||||
const mapped = graph.map((value, vertex) => vertex + '_mapped');
|
||||
expect(mapped).toEqual(vertexMap.map(v => v + '_mapped'));
|
||||
});
|
||||
|
||||
test('reduce should accumulate a value based on each vertex', () => {
|
||||
it('reduce should accumulate a value based on each vertex', () => {
|
||||
const concatenated = graph.reduce((acc, value, key) => acc + key, '');
|
||||
expect(concatenated).toBe(vertexMap.join(''));
|
||||
});
|
||||
|
||||
test('Removing an edge of a DirectedGraph should delete additional edges', () => {
|
||||
it('Removing an edge of a DirectedGraph should delete additional edges', () => {
|
||||
const dg = new DirectedGraph();
|
||||
dg.addVertex('hello');
|
||||
dg.addVertex('hi');
|
||||
|
@ -705,7 +719,7 @@ describe('DirectedGraph iterative Methods', () => {
|
|||
expect(dg.incomingEdgesOf('Hi')).toEqual([]);
|
||||
});
|
||||
|
||||
test('Removing a vertex of a DirectedGraph should delete additional edges', () => {
|
||||
it('Removing a vertex of a DirectedGraph should delete additional edges', () => {
|
||||
const graph = new DirectedGraph();
|
||||
|
||||
graph.addVertex('Hello');
|
||||
|
@ -717,7 +731,7 @@ describe('DirectedGraph iterative Methods', () => {
|
|||
expect(graph.incomingEdgesOf('Hi')).toEqual([]);
|
||||
});
|
||||
|
||||
test('Removing a vertex from a DirectedGraph should remove its edges', () => {
|
||||
it('Removing a vertex from a DirectedGraph should remove its edges', () => {
|
||||
const dg = new DirectedGraph();
|
||||
dg.addVertex('hello');
|
||||
dg.addVertex('world');
|
||||
|
@ -740,7 +754,7 @@ describe('DirectedGraph iterative Methods', () => {
|
|||
});
|
||||
|
||||
describe('DirectedGraph getCycles', () => {
|
||||
test('should getCycles return correct result', () => {
|
||||
it('should getCycles return correct result', () => {
|
||||
const graph = new DirectedGraph();
|
||||
graph.addVertex('A');
|
||||
graph.addVertex('B');
|
||||
|
@ -758,7 +772,7 @@ describe('DirectedGraph getCycles', () => {
|
|||
expect(cycles[0]).toEqual(['B', 'D', 'E']);
|
||||
});
|
||||
|
||||
test('should simple cycles graph getCycles return correct result', () => {
|
||||
it('should simple cycles graph getCycles return correct result', () => {
|
||||
const graph = new DirectedGraph();
|
||||
|
||||
graph.addVertex('A');
|
||||
|
@ -779,7 +793,7 @@ describe('DirectedGraph getCycles', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should 3 cycles graph getCycles return correct result', () => {
|
||||
it('should 3 cycles graph getCycles return correct result', () => {
|
||||
const graph = new DirectedGraph();
|
||||
|
||||
graph.addVertex('A');
|
||||
|
@ -812,7 +826,7 @@ describe('DirectedGraph getCycles', () => {
|
|||
});
|
||||
|
||||
describe('DirectedGraph tarjan', () => {
|
||||
test('should simple cycles graph tarjan cycles return correct result', () => {
|
||||
it('should simple cycles graph tarjan cycles return correct result', () => {
|
||||
const graph = new DirectedGraph();
|
||||
|
||||
graph.addVertex('A');
|
||||
|
@ -853,14 +867,14 @@ describe('DirectedGraph tarjan', () => {
|
|||
return graph;
|
||||
}
|
||||
|
||||
test('should tarjan cycles return correct result', () => {
|
||||
it('should tarjan cycles return correct result', () => {
|
||||
const graph = createExampleGraph1();
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(1);
|
||||
expect(cycles).toEqual([['B', 'D', 'E']]);
|
||||
});
|
||||
|
||||
test('should tarjan SCCs return correct result', () => {
|
||||
it('should tarjan SCCs return correct result', () => {
|
||||
const graph = createExampleGraph1();
|
||||
const sccs = graph.tarjan().SCCs;
|
||||
expect(sccs.size).toBe(3);
|
||||
|
@ -878,7 +892,7 @@ describe('DirectedGraph tarjan', () => {
|
|||
return graph;
|
||||
}
|
||||
|
||||
test('should 3 cycles graph tarjan cycles return correct result', () => {
|
||||
it('should 3 cycles graph tarjan cycles return correct result', () => {
|
||||
const graph = createExampleGraph2();
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(3);
|
||||
|
@ -889,7 +903,7 @@ describe('DirectedGraph tarjan', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should 3 cycles graph tarjan SCCs return correct result', () => {
|
||||
it('should 3 cycles graph tarjan SCCs return correct result', () => {
|
||||
const graph = createExampleGraph2();
|
||||
const sccs = graph.tarjan().SCCs;
|
||||
expect(sccs.size).toBe(2);
|
||||
|
@ -919,7 +933,7 @@ describe('DirectedGraph tarjan', () => {
|
|||
return graph;
|
||||
}
|
||||
|
||||
test('should cuttable graph tarjan cycles return correct result', () => {
|
||||
it('should cuttable graph tarjan cycles return correct result', () => {
|
||||
const graph = createExampleGraph3();
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(2);
|
||||
|
@ -929,7 +943,7 @@ describe('DirectedGraph tarjan', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should cuttable graph tarjan SCCs return correct result', () => {
|
||||
it('should cuttable graph tarjan SCCs return correct result', () => {
|
||||
const graph = createExampleGraph3();
|
||||
const sccs = graph.tarjan().SCCs;
|
||||
expect(sccs.size).toBe(3);
|
||||
|
@ -951,7 +965,7 @@ describe('DirectedGraph tarjan', () => {
|
|||
return graph;
|
||||
}
|
||||
|
||||
test('should more cuttable graph tarjan cycles return correct result', () => {
|
||||
it('should more cuttable graph tarjan cycles return correct result', () => {
|
||||
const graph = createExampleGraph4();
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(4);
|
||||
|
@ -963,7 +977,7 @@ describe('DirectedGraph tarjan', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should more cuttable graph tarjan SCCs return correct result', () => {
|
||||
it('should more cuttable graph tarjan SCCs return correct result', () => {
|
||||
const graph = createExampleGraph4();
|
||||
const sccs = graph.tarjan().SCCs;
|
||||
expect(sccs.size).toBe(3);
|
||||
|
@ -976,7 +990,7 @@ describe('DirectedGraph tarjan', () => {
|
|||
return graph;
|
||||
}
|
||||
|
||||
test('should uncuttable graph tarjan cycles return correct result', () => {
|
||||
it('should uncuttable graph tarjan cycles return correct result', () => {
|
||||
const graph = createExampleGraph5();
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(4);
|
||||
|
@ -988,7 +1002,7 @@ describe('DirectedGraph tarjan', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should uncuttable graph tarjan SCCs return correct result', () => {
|
||||
it('should uncuttable graph tarjan SCCs return correct result', () => {
|
||||
const graph = createExampleGraph5();
|
||||
const sccs = graph.tarjan().SCCs;
|
||||
expect(sccs.size).toBe(3);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { MapEdge, MapGraph, MapVertex } from '../../../../src';
|
||||
|
||||
describe('MapGraph Operation Test', () => {
|
||||
it('dijkstra shortest path', () => {
|
||||
const mapGraph = new MapGraph([5.500338, 100.173665]);
|
||||
let mapGraph: MapGraph;
|
||||
beforeEach(() => {
|
||||
mapGraph = new MapGraph([5.500338, 100.173665]);
|
||||
|
||||
mapGraph.addVertex(new MapVertex('Surin', '', 5.466724, 100.274805));
|
||||
mapGraph.addVertex(new MapVertex('Batu Feringgi Beach', '', 5.475141, 100.27667));
|
||||
|
@ -27,6 +28,9 @@ describe('MapGraph Operation Test', () => {
|
|||
mapGraph.addEdge('Trinity Auto', 'Saanen Goat Farm', 26.3);
|
||||
mapGraph.addEdge('The Breeza', 'Penang Airport', 24.8);
|
||||
mapGraph.addEdge('Penang Airport', 'Saanen Goat Farm', 21.2);
|
||||
});
|
||||
|
||||
it('dijkstra shortest path', () => {
|
||||
const expected1 = ['Surin', 'Lotus', 'The Breeza', 'Trinity Auto', 'Saanen Goat Farm'];
|
||||
|
||||
const minPathBetween = mapGraph.getMinPathBetween('Surin', 'Saanen Goat Farm');
|
||||
|
@ -42,6 +46,24 @@ describe('MapGraph Operation Test', () => {
|
|||
expect(surinToSaanenGoatFarmViaDij?.minPath.map(v => v.key)).toEqual(expected2);
|
||||
expect(surinToSaanenGoatFarmViaDij?.minDist).toBe(25.2);
|
||||
});
|
||||
|
||||
it('should clone', () => {
|
||||
const cloned = mapGraph.clone();
|
||||
const expected1 = ['Surin', 'Lotus', 'The Breeza', 'Trinity Auto', 'Saanen Goat Farm'];
|
||||
|
||||
const minPathBetween = cloned.getMinPathBetween('Surin', 'Saanen Goat Farm');
|
||||
expect(minPathBetween?.map(v => v.key)).toEqual(expected1);
|
||||
const surinToSaanenGoatFarmDij = cloned.dijkstra('Surin', 'Saanen Goat Farm', true, true);
|
||||
expect(surinToSaanenGoatFarmDij?.minPath.map(v => v.key)).toEqual(expected1);
|
||||
expect(surinToSaanenGoatFarmDij?.minDist).toBe(41.1);
|
||||
cloned.addEdge('Surin', 'Batu Feringgi Beach', 1.5);
|
||||
const expected2 = ['Surin', 'Batu Feringgi Beach', 'Hard Rock Hotel', 'Saanen Goat Farm'];
|
||||
const minPathBetweenViaBFB = cloned.getMinPathBetween('Surin', 'Saanen Goat Farm', true);
|
||||
expect(minPathBetweenViaBFB?.map(v => v.key)).toEqual(expected2);
|
||||
const surinToSaanenGoatFarmViaDij = cloned.dijkstra('Surin', 'Saanen Goat Farm', true, true);
|
||||
expect(surinToSaanenGoatFarmViaDij?.minPath.map(v => v.key)).toEqual(expected2);
|
||||
expect(surinToSaanenGoatFarmViaDij?.minDist).toBe(25.2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('MapGraph', () => {
|
||||
|
|
|
@ -174,7 +174,7 @@ describe('UndirectedGraph', () => {
|
|||
expect(minWeightedPath?.minPath?.[4]?.key).toBe('Intersection_5');
|
||||
});
|
||||
|
||||
test('Removing an edge of a UndirectedGraph should not delete additional edges', () => {
|
||||
it('Removing an edge of a UndirectedGraph should not delete additional edges', () => {
|
||||
const dg = new UndirectedGraph();
|
||||
dg.addVertex('hello');
|
||||
dg.addVertex('hi');
|
||||
|
@ -190,7 +190,7 @@ describe('UndirectedGraph', () => {
|
|||
expect(dg.getEdge('hello', 'hey')).toBeInstanceOf(UndirectedEdge);
|
||||
});
|
||||
|
||||
test('Removing a vertex of a UndirectedGraph should delete additional edges', () => {
|
||||
it('Removing a vertex of a UndirectedGraph should delete additional edges', () => {
|
||||
const graph = new UndirectedGraph();
|
||||
|
||||
graph.addVertex('Hello');
|
||||
|
@ -202,7 +202,7 @@ describe('UndirectedGraph', () => {
|
|||
expect(graph.edgesOf('Hi')).toEqual([]);
|
||||
});
|
||||
|
||||
test('Removing a vertex from a UndirectedGraph should remove its edges', () => {
|
||||
it('Removing a vertex from a UndirectedGraph should remove its edges', () => {
|
||||
const dg = new UndirectedGraph();
|
||||
dg.addVertex('hello');
|
||||
dg.addVertex('world');
|
||||
|
@ -274,7 +274,7 @@ it('Should return Infinity if dest is not found', () => {
|
|||
});
|
||||
|
||||
describe('UndirectedGraph getCycles', () => {
|
||||
test('should getCycles return correct result', () => {
|
||||
it('should getCycles return correct result', () => {
|
||||
const graph = new UndirectedGraph();
|
||||
graph.addVertex('A');
|
||||
graph.addVertex('B');
|
||||
|
@ -296,7 +296,7 @@ describe('UndirectedGraph getCycles', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should simple cycles graph getCycles return correct result', () => {
|
||||
it('should simple cycles graph getCycles return correct result', () => {
|
||||
const graph = new UndirectedGraph();
|
||||
|
||||
graph.addVertex('A');
|
||||
|
@ -318,7 +318,7 @@ describe('UndirectedGraph getCycles', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should 3 cycles graph getCycles return correct result', () => {
|
||||
it('should 3 cycles graph getCycles return correct result', () => {
|
||||
const graph = new UndirectedGraph();
|
||||
|
||||
graph.addVertex('A');
|
||||
|
@ -358,7 +358,7 @@ describe('UndirectedGraph getCycles', () => {
|
|||
});
|
||||
|
||||
describe('UndirectedGraph tarjan', () => {
|
||||
test('should simple cycles graph tarjan cycles return correct result', () => {
|
||||
it('should simple cycles graph tarjan cycles return correct result', () => {
|
||||
const graph = new UndirectedGraph();
|
||||
|
||||
graph.addVertex('A');
|
||||
|
@ -396,38 +396,38 @@ describe('UndirectedGraph tarjan', () => {
|
|||
return graph;
|
||||
}
|
||||
|
||||
test('should tarjan cut vertexes return correct result', () => {
|
||||
it('should tarjan cut vertexes return correct result', () => {
|
||||
const graph = createExampleGraph1();
|
||||
const cutVertices = graph.tarjan().cutVertices;
|
||||
expect(cutVertices.length).toBe(0);
|
||||
});
|
||||
|
||||
test('should tarjan bridges return correct result', () => {
|
||||
it('should tarjan bridges return correct result', () => {
|
||||
const graph = createExampleGraph1();
|
||||
const bridges = graph.tarjan().bridges;
|
||||
expect(bridges.length).toBe(0);
|
||||
});
|
||||
|
||||
test('should 3 cycles graph tarjan cut vertexes return correct result', () => {
|
||||
it('should 3 cycles graph tarjan cut vertexes return correct result', () => {
|
||||
const graph = createExampleGraph1();
|
||||
const cutVertices = graph.tarjan().cutVertices;
|
||||
expect(cutVertices.length).toBe(0);
|
||||
});
|
||||
|
||||
test('should 3 cycles graph tarjan bridges return correct result', () => {
|
||||
it('should 3 cycles graph tarjan bridges return correct result', () => {
|
||||
const graph = createExampleGraph1();
|
||||
const bridges = graph.tarjan().bridges;
|
||||
expect(bridges.length).toBe(0);
|
||||
});
|
||||
|
||||
test('should cuttable graph tarjan cut vertexes return correct result', () => {
|
||||
it('should cuttable graph tarjan cut vertexes return correct result', () => {
|
||||
const graph = createExampleGraph3();
|
||||
const cutVertices = graph.tarjan().cutVertices;
|
||||
expect(cutVertices.length).toBe(3);
|
||||
expect(cutVertices.map(cv => cv.key)).toEqual(['B', 'E', 'A']);
|
||||
});
|
||||
|
||||
test('should cuttable graph tarjan bridges return correct result', () => {
|
||||
it('should cuttable graph tarjan bridges return correct result', () => {
|
||||
const graph = createExampleGraph3();
|
||||
const bridges = graph.tarjan().bridges;
|
||||
expect(bridges.length).toBe(2);
|
||||
|
@ -437,14 +437,14 @@ describe('UndirectedGraph tarjan', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should more cuttable graph tarjan cut vertexes return correct result', () => {
|
||||
it('should more cuttable graph tarjan cut vertexes return correct result', () => {
|
||||
const graph = createExampleGraph4();
|
||||
const cutVertices = graph.tarjan().cutVertices;
|
||||
expect(cutVertices.length).toBe(4);
|
||||
expect(cutVertices.map(cv => cv.key)).toEqual(['H', 'B', 'E', 'A']);
|
||||
});
|
||||
|
||||
test('should more cuttable graph tarjan bridges return correct result', () => {
|
||||
it('should more cuttable graph tarjan bridges return correct result', () => {
|
||||
const graph = createExampleGraph4();
|
||||
const bridges = graph.tarjan().bridges;
|
||||
expect(bridges.length).toBe(2);
|
||||
|
@ -454,13 +454,13 @@ describe('UndirectedGraph tarjan', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should uncuttable graph tarjan cut vertexes return correct result', () => {
|
||||
it('should uncuttable graph tarjan cut vertexes return correct result', () => {
|
||||
const graph = createExampleGraph5();
|
||||
const cutVertices = graph.tarjan().cutVertices;
|
||||
expect(cutVertices.length).toBe(1);
|
||||
});
|
||||
|
||||
test('should uncuttable graph tarjan bridges return correct result', () => {
|
||||
it('should uncuttable graph tarjan bridges return correct result', () => {
|
||||
const graph = createExampleGraph5();
|
||||
const bridges = graph.tarjan().bridges;
|
||||
expect(bridges.length).toBe(0);
|
||||
|
@ -477,7 +477,7 @@ describe('UndirectedGraph tarjan', () => {
|
|||
return graph;
|
||||
}
|
||||
|
||||
test('should 3 cycles graph tarjan cycles return correct result', () => {
|
||||
it('should 3 cycles graph tarjan cycles return correct result', () => {
|
||||
const graph = createExampleGraph2();
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(10);
|
||||
|
@ -515,7 +515,7 @@ describe('UndirectedGraph tarjan', () => {
|
|||
return graph;
|
||||
}
|
||||
|
||||
test('should cuttable graph tarjan cycles return correct result', () => {
|
||||
it('should cuttable graph tarjan cycles return correct result', () => {
|
||||
const graph = createExampleGraph3();
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(2);
|
||||
|
@ -525,7 +525,7 @@ describe('UndirectedGraph tarjan', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
// test('should cuttable graph tarjan CCs return correct result', () => {
|
||||
// it('should cuttable graph tarjan CCs return correct result', () => {
|
||||
// const graph = createExampleGraph3();
|
||||
// const ccs = graph.tarjan().CCs;
|
||||
// expect(ccs.size).toBe(3);
|
||||
|
@ -547,7 +547,7 @@ describe('UndirectedGraph tarjan', () => {
|
|||
return graph;
|
||||
}
|
||||
|
||||
test('should more cuttable graph tarjan cycles return correct result', () => {
|
||||
it('should more cuttable graph tarjan cycles return correct result', () => {
|
||||
const graph = createExampleGraph4();
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(5);
|
||||
|
@ -560,7 +560,7 @@ describe('UndirectedGraph tarjan', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
// test('should more cuttable graph tarjan SCCs return correct result', () => {
|
||||
// it('should more cuttable graph tarjan SCCs return correct result', () => {
|
||||
// const graph = createExampleGraph4();
|
||||
// const ccs = graph.tarjan().CCs;
|
||||
// expect(ccs.size).toBe(3);
|
||||
|
@ -573,7 +573,7 @@ describe('UndirectedGraph tarjan', () => {
|
|||
return graph;
|
||||
}
|
||||
|
||||
test('should uncuttable graph tarjan cycles return correct result', () => {
|
||||
it('should uncuttable graph tarjan cycles return correct result', () => {
|
||||
const graph = createExampleGraph5();
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(13);
|
||||
|
@ -594,7 +594,7 @@ describe('UndirectedGraph tarjan', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
// test('should uncuttable graph tarjan SCCs return correct result', () => {
|
||||
// it('should uncuttable graph tarjan SCCs return correct result', () => {
|
||||
// const graph = createExampleGraph5();
|
||||
// const ccs = graph.tarjan().CCs;
|
||||
// expect(ccs.size).toBe(3);
|
||||
|
|
|
@ -13,7 +13,7 @@ describe('HashMap', () => {
|
|||
expect(hashMap.isEmpty()).toBe(true);
|
||||
});
|
||||
|
||||
it('should put and get values', () => {
|
||||
it('should set and get values', () => {
|
||||
hashMap.set('one', 1);
|
||||
hashMap.set('two', 2);
|
||||
hashMap.set('three', 3);
|
||||
|
@ -127,10 +127,11 @@ describe('HashMap', () => {
|
|||
it('should handle object keys correctly', () => {
|
||||
const keyObj = { id: 1 };
|
||||
hashMap.set(keyObj, 'objectValue');
|
||||
expect(hashMap.has(keyObj)).toBe(true);
|
||||
expect(hashMap.get(keyObj)).toBe('objectValue');
|
||||
});
|
||||
|
||||
test('Inheritability test', () => {
|
||||
it('Inheritability test', () => {
|
||||
class ExtendedHashMap<K, V> extends HashMap<K, V> {
|
||||
someOtherParam?: string;
|
||||
|
||||
|
@ -154,7 +155,7 @@ describe('HashMap', () => {
|
|||
expect(eHM.get('one')).toBe(1);
|
||||
});
|
||||
|
||||
test('should raw elements toEntry', () => {
|
||||
it('should raw elements toEntry', () => {
|
||||
const rawCollection = [
|
||||
{ id: 1, name: 'item 1' },
|
||||
{ id: 2, name: 'item 2' }
|
||||
|
@ -238,17 +239,19 @@ describe('HashMap', () => {
|
|||
describe('HashMap for coordinate object keys', () => {
|
||||
const hashMap: HashMap<[number, number], number> = new HashMap();
|
||||
const codObjs: [number, number][] = [];
|
||||
|
||||
test('set elements in hash map', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const codObj: [number, number] = [getRandomInt(-10000, 10000), i];
|
||||
codObjs.push(codObj);
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const codObj: [number, number] = [getRandomInt(-10000, 10000), i];
|
||||
codObjs.push(codObj);
|
||||
}
|
||||
it('set elements in hash map', () => {
|
||||
for (let i = 0; i < codObjs.length; i++) {
|
||||
const codObj = codObjs[i];
|
||||
hashMap.set(codObj, i);
|
||||
}
|
||||
});
|
||||
|
||||
test('get elements in hash map', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
it('get elements in hash map', () => {
|
||||
for (let i = 0; i < codObjs.length; i++) {
|
||||
const codObj = codObjs[i];
|
||||
if (codObj) {
|
||||
expect(hashMap.get(codObj)).toBe(i);
|
||||
|
@ -256,8 +259,12 @@ describe('HashMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
test('delete elements in hash map', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
it('should spread elements in hash map', () => {
|
||||
expect([...hashMap]).toEqual(codObjs.map(codObj => [codObj, codObj[1]]));
|
||||
});
|
||||
|
||||
it('delete elements in hash map', () => {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (i === 500) expect(hashMap.size).toBe(500);
|
||||
const codObj = codObjs[i];
|
||||
if (codObj) hashMap.delete(codObj);
|
||||
|
@ -285,11 +292,11 @@ describe('HashMap', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('keys', () => {
|
||||
it('keys', () => {
|
||||
expect([...hm.keys()]).toEqual([2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
test('values', () => {
|
||||
it('values', () => {
|
||||
expect([...hm.values()]).toEqual([2, 3, 4, 5, 6]);
|
||||
});
|
||||
});
|
||||
|
@ -304,31 +311,31 @@ describe('HashMap', () => {
|
|||
hashMap.set('key3', 'value3');
|
||||
});
|
||||
|
||||
test('every() returns true if all elements match the condition', () => {
|
||||
it('every() returns true if all elements match the condition', () => {
|
||||
expect(hashMap.every(value => typeof value === 'string')).toBe(true);
|
||||
});
|
||||
|
||||
test('some() returns true if any element matches the condition', () => {
|
||||
it('some() returns true if any element matches the condition', () => {
|
||||
expect(hashMap.some((value, key) => key === 'key1')).toBe(true);
|
||||
});
|
||||
|
||||
test('forEach() should execute a function for each element', () => {
|
||||
it('forEach() should execute a function for each element', () => {
|
||||
const mockCallback = jest.fn();
|
||||
hashMap.forEach(mockCallback);
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
});
|
||||
|
||||
test('map() should transform each element', () => {
|
||||
it('map() should transform each element', () => {
|
||||
const newHashMap = hashMap.map(value => value.toUpperCase());
|
||||
expect(newHashMap.get('key1')).toBe('VALUE1');
|
||||
});
|
||||
|
||||
test('filter() should remove elements that do not match the condition', () => {
|
||||
it('filter() should remove elements that do not match the condition', () => {
|
||||
const filteredHashMap = hashMap.filter((value, key) => key !== 'key1');
|
||||
expect(filteredHashMap.has('key1')).toBe(false);
|
||||
});
|
||||
|
||||
test('reduce() should accumulate values', () => {
|
||||
it('reduce() should accumulate values', () => {
|
||||
const result = hashMap.reduce((acc, value) => acc + value, '');
|
||||
expect(result).toBe('value1value2value3');
|
||||
});
|
||||
|
@ -347,6 +354,7 @@ describe('LinkedHashMap', () => {
|
|||
});
|
||||
|
||||
it('should add a key-value pair', () => {
|
||||
expect(hashMap.first).toBe(undefined);
|
||||
hashMap.set('key1', 'value1');
|
||||
expect(hashMap.get('key1')).toBe('value1');
|
||||
});
|
||||
|
@ -441,29 +449,99 @@ describe('LinkedHashMap', () => {
|
|||
compareHashMaps(hashMap, stdMap);
|
||||
});
|
||||
|
||||
test('should iterate correctly with reverse iterators', () => {
|
||||
it('should iterate correctly with reverse iterators', () => {
|
||||
hashMap.set('key1', 'value1');
|
||||
hashMap.set('key2', 'value2');
|
||||
const iterator = hashMap.reverseBegin();
|
||||
expect(iterator.next().value).toEqual(['key2', 'value2']);
|
||||
});
|
||||
|
||||
test('should return the last element', () => {
|
||||
it('should return the last element', () => {
|
||||
hashMap.set('key1', 'value1');
|
||||
hashMap.set('key2', 'value2');
|
||||
expect(hashMap.last).toEqual(['key2', 'value2']);
|
||||
});
|
||||
|
||||
test('should return undefined for empty map', () => {
|
||||
it('should return undefined for empty map', () => {
|
||||
expect(hashMap.last).toBeUndefined();
|
||||
});
|
||||
|
||||
test('should get element at specific index', () => {
|
||||
it('should get element at specific index', () => {
|
||||
hashMap.set('key1', 'value1');
|
||||
hashMap.set('key2', 'value2');
|
||||
expect(hashMap.at(1)).toBe('value2');
|
||||
});
|
||||
|
||||
it('should hashFn, objHashFn, toEntryFn work well', () => {
|
||||
const data: Array<{ name: number }> = [{ name: 1 }, { name: 2 }, { name: 3 }];
|
||||
const hm = new LinkedHashMap(data, {
|
||||
hashFn: key => String(key),
|
||||
objHashFn: obj => obj,
|
||||
toEntryFn: ({ name }) => [{ name }, name]
|
||||
});
|
||||
|
||||
expect(hm.hashFn).toBeTruthy();
|
||||
expect(hm.objHashFn).toBeTruthy();
|
||||
expect(hm.toEntryFn).toBeTruthy();
|
||||
expect([...hm]).toEqual([
|
||||
[{ name: 1 }, 1],
|
||||
[{ name: 2 }, 2],
|
||||
[{ name: 3 }, 3]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should begin, reverseBegin', () => {
|
||||
const data: Array<{ name: number }> = [{ name: 1 }, { name: 2 }, { name: 3 }];
|
||||
const hm = new LinkedHashMap(data, {
|
||||
hashFn: key => String(key),
|
||||
objHashFn: obj => obj,
|
||||
toEntryFn: ({ name }) => [{ name }, name]
|
||||
});
|
||||
|
||||
expect(hm.begin().next()).toEqual({
|
||||
done: false,
|
||||
value: [
|
||||
{
|
||||
name: 1
|
||||
},
|
||||
1
|
||||
]
|
||||
});
|
||||
|
||||
expect(hm.reverseBegin().next()).toEqual({
|
||||
done: false,
|
||||
value: [
|
||||
{
|
||||
name: 3
|
||||
},
|
||||
3
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('should clone', () => {
|
||||
hashMap = new LinkedHashMap<string, number>();
|
||||
|
||||
hashMap.set('one', 1);
|
||||
hashMap.set('two', 2);
|
||||
for (let i = 3; i <= 100; i++) {
|
||||
hashMap.set(i.toString(), i);
|
||||
}
|
||||
|
||||
expect(hashMap.get('one')).toBe(1);
|
||||
expect(hashMap.get('two')).toBe(2);
|
||||
expect(hashMap.get('86')).toBe(86);
|
||||
expect(hashMap.size).toBe(100);
|
||||
hashMap.delete('two');
|
||||
expect(hashMap.size).toBe(99);
|
||||
|
||||
const cloned = hashMap.clone();
|
||||
expect(cloned.get('one')).toBe(1);
|
||||
expect(cloned.get('two')).toBe(undefined);
|
||||
expect(cloned.get('86')).toBe(86);
|
||||
expect(cloned.size).toBe(99);
|
||||
});
|
||||
|
||||
describe('LinkedHashMap basic', () => {
|
||||
let hashMap: LinkedHashMap<string, number>;
|
||||
|
||||
|
@ -506,6 +584,9 @@ describe('LinkedHashMap', () => {
|
|||
hashMap.delete('one');
|
||||
expect(hashMap.get('one')).toBeUndefined();
|
||||
expect(hashMap.size).toBe(1);
|
||||
hashMap.deleteAt(0);
|
||||
// expect(hashMap.get('two')).toBe(undefined); // TODO #99
|
||||
expect(hashMap.size).toBe(0);
|
||||
});
|
||||
|
||||
it('should clear the LinkedHashMap', () => {
|
||||
|
@ -570,7 +651,7 @@ describe('LinkedHashMap', () => {
|
|||
const hashMap: LinkedHashMap<[number, number], number> = new LinkedHashMap();
|
||||
const codObjs: [number, number][] = [];
|
||||
|
||||
test('set elements in hash map', () => {
|
||||
it('set elements in hash map', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const codObj: [number, number] = [getRandomInt(-10000, 10000), i];
|
||||
codObjs.push(codObj);
|
||||
|
@ -578,7 +659,7 @@ describe('LinkedHashMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
test('get elements in hash map', () => {
|
||||
it('get elements in hash map', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const codObj = codObjs[i];
|
||||
if (codObj) {
|
||||
|
@ -587,7 +668,7 @@ describe('LinkedHashMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
test('delete elements in hash map', () => {
|
||||
it('delete elements in hash map', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
if (i === 500) expect(hashMap.size).toBe(500);
|
||||
const codObj = codObjs[i];
|
||||
|
@ -616,15 +697,15 @@ describe('LinkedHashMap', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('keys', () => {
|
||||
it('keys', () => {
|
||||
expect([...hm.keys()]).toEqual([2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
test('values', () => {
|
||||
it('values', () => {
|
||||
expect([...hm.values()]).toEqual([2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
test('entries', () => {
|
||||
it('entries', () => {
|
||||
expect([...hm.entries()]).toEqual([
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
|
@ -634,21 +715,61 @@ describe('LinkedHashMap', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('every', () => {
|
||||
it('every', () => {
|
||||
expect(hm.every(value => value > 4)).toBe(false);
|
||||
});
|
||||
|
||||
test('some', () => {
|
||||
it('some', () => {
|
||||
expect(hm.some(value => value > 6)).toBe(false);
|
||||
});
|
||||
|
||||
test('hasValue', () => {
|
||||
it('hasValue', () => {
|
||||
expect(hm.hasValue(3)).toBe(true);
|
||||
expect(hm.hasValue(7)).toBe(false);
|
||||
});
|
||||
|
||||
test('print', () => {
|
||||
it('print', () => {
|
||||
// hm.print();
|
||||
});
|
||||
});
|
||||
|
||||
describe('HashMap HOF', () => {
|
||||
let hashMap: LinkedHashMap;
|
||||
|
||||
beforeEach(() => {
|
||||
hashMap = new LinkedHashMap<string, string>();
|
||||
hashMap.set('key1', 'value1');
|
||||
hashMap.set('key2', 'value2');
|
||||
hashMap.set('key3', 'value3');
|
||||
});
|
||||
|
||||
it('every() returns true if all elements match the condition', () => {
|
||||
expect(hashMap.every(value => typeof value === 'string')).toBe(true);
|
||||
});
|
||||
|
||||
it('some() returns true if any element matches the condition', () => {
|
||||
expect(hashMap.some((value, key) => key === 'key1')).toBe(true);
|
||||
});
|
||||
|
||||
it('forEach() should execute a function for each element', () => {
|
||||
const mockCallback = jest.fn();
|
||||
hashMap.forEach(mockCallback);
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
});
|
||||
|
||||
it('map() should transform each element', () => {
|
||||
const newHashMap = hashMap.map(value => value.toUpperCase());
|
||||
expect(newHashMap.get('key1')).toBe('VALUE1');
|
||||
});
|
||||
|
||||
it('filter() should remove elements that do not match the condition', () => {
|
||||
const filteredHashMap = hashMap.filter((value, key) => key !== 'key1');
|
||||
expect(filteredHashMap.has('key1')).toBe(false);
|
||||
});
|
||||
|
||||
it('reduce() should accumulate values', () => {
|
||||
const result = hashMap.reduce((acc, value) => acc + value, '');
|
||||
expect(result).toBe('value1value2value3');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,9 +2,15 @@ import { FibonacciHeap, Heap, MaxHeap, MinHeap } from '../../../../src';
|
|||
import { logBigOMetricsWrap } from '../../../utils';
|
||||
|
||||
describe('Heap Operation Test', () => {
|
||||
it('should initiate heap', function () {
|
||||
const hp = new Heap<number>();
|
||||
hp.add(1);
|
||||
expect(hp.size).toBe(1);
|
||||
});
|
||||
|
||||
it('should heap add and delete work well', function () {
|
||||
const hp = new MinHeap<number>();
|
||||
|
||||
expect(hp.delete(1)).toBe(false);
|
||||
hp.add(2);
|
||||
hp.add(3);
|
||||
hp.add(1);
|
||||
|
@ -23,6 +29,7 @@ describe('Heap Operation Test', () => {
|
|||
|
||||
it('should numeric heap work well', function () {
|
||||
const minNumHeap = new MinHeap<number>();
|
||||
expect(minNumHeap.poll()).toBe(undefined);
|
||||
minNumHeap.add(1);
|
||||
minNumHeap.add(6);
|
||||
minNumHeap.add(2);
|
||||
|
@ -219,8 +226,47 @@ describe('Heap Operation Test', () => {
|
|||
|
||||
expect([...heap.sort()]).toEqual([1, 3, 4, 5, 6, 7, 8]);
|
||||
});
|
||||
|
||||
it('should getter leaf', function () {
|
||||
const hp = new Heap<number>();
|
||||
expect(hp.leaf).toBe(undefined);
|
||||
hp.add(1);
|
||||
expect(hp.leaf).toBe(1);
|
||||
});
|
||||
|
||||
it('should error', function () {
|
||||
expect(() => {
|
||||
new Heap([{ key: 1 }, { key: 2 }, { key: 3 }]);
|
||||
}).toThrow(
|
||||
"When comparing object types, a custom comparator must be defined in the constructor's options parameter."
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Heap HOF', () => {
|
||||
let hp: Heap;
|
||||
|
||||
beforeEach(() => {
|
||||
hp = new Heap([{ key: 1 }, { key: 2 }, { key: 3 }], { comparator: (a, b) => a.key - b.key });
|
||||
});
|
||||
|
||||
it('should filter', () => {
|
||||
const filtered = hp.filter(({ key }) => key % 2 === 1);
|
||||
expect([...filtered]).toEqual([{ key: 1 }, { key: 3 }]);
|
||||
});
|
||||
|
||||
it('should map', () => {
|
||||
const mapped = hp.map(
|
||||
({ key }) => [key, key],
|
||||
(a, b) => a[0] - b[0]
|
||||
);
|
||||
expect([...mapped]).toEqual([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3]
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('FibonacciHeap', () => {
|
||||
let heap: FibonacciHeap<number>;
|
||||
|
||||
|
@ -411,41 +457,3 @@ describe('FibonacciHeap Stress Test', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
// describe('Competitor performance compare', () => {
|
||||
// const minHeap = new MinHeap<number>();
|
||||
// const cHeap = new CHeap<number>();
|
||||
// const cPQ = new PriorityQueue<number>(undefined, (a, b) => a - b);
|
||||
// const n = 100000;
|
||||
//
|
||||
// it('should add performance well', () => {
|
||||
// const heapCost = calcRunTime(() => {
|
||||
// for (let i = 0; i < n; i++) {
|
||||
// minHeap.add(i);
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// console.log(`heapCost: ${heapCost}`)
|
||||
// });
|
||||
//
|
||||
// it('should add performance well', () => {
|
||||
//
|
||||
// const cHeapCost = calcRunTime(() => {
|
||||
// for (let i = 0; i < n; i++) {
|
||||
// cHeap.push(i);
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// console.log(`cHeapCost: ${cHeapCost}`)
|
||||
// });
|
||||
//
|
||||
// it('should add performance well', () => {
|
||||
//
|
||||
// const cPQCost = calcRunTime(() => {
|
||||
// for (let i = 0; i < n; i++) {
|
||||
// cPQ.push(i);
|
||||
// }
|
||||
// })
|
||||
// console.log(`cPQCost: ${cPQCost}`)
|
||||
// });
|
||||
// });
|
||||
|
|
|
@ -90,22 +90,22 @@ describe('Heap iterative methods', () => {
|
|||
}
|
||||
});
|
||||
|
||||
test('Heap is iterable', () => {
|
||||
it('Heap is iterable', () => {
|
||||
expect([...heap]).toEqual([10, 20, 30, 40, 50, 60, 70, 80, 90, 100]);
|
||||
});
|
||||
|
||||
test('forEach method calls a function for each element', () => {
|
||||
it('forEach method calls a function for each element', () => {
|
||||
const mockCallback = jest.fn();
|
||||
heap.forEach(mockCallback);
|
||||
expect(mockCallback.mock.calls.length).toBe(10);
|
||||
});
|
||||
|
||||
test('filter method returns filtered elements', () => {
|
||||
it('filter method returns filtered elements', () => {
|
||||
const result = heap.filter(x => x > 50);
|
||||
expect([...result]).toEqual([60, 70, 80, 90, 100]);
|
||||
});
|
||||
|
||||
test('map method correctly maps elements', () => {
|
||||
it('map method correctly maps elements', () => {
|
||||
const result = heap.map(
|
||||
x => x / 10,
|
||||
(a: number, b: number) => a - b
|
||||
|
@ -113,7 +113,7 @@ describe('Heap iterative methods', () => {
|
|||
expect([...result]).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
});
|
||||
|
||||
test('reduce method correctly reduces elements', () => {
|
||||
it('reduce method correctly reduces elements', () => {
|
||||
const result = heap.reduce((acc, curr) => acc + curr, 0);
|
||||
expect(result).toBe(550); // 10+20+...+100 = 550
|
||||
});
|
||||
|
|
|
@ -20,14 +20,27 @@ describe('DoublyLinkedList Operation Test', () => {
|
|||
expect(list.getNodeAt(-1)).toBe(undefined);
|
||||
expect(list.getNodeAt(5)).toBe(undefined);
|
||||
expect(list.addAt(5, 6)).toBe(true);
|
||||
expect(list.addAt(-1, 6)).toBe(false);
|
||||
expect(list.addAt(7, 6)).toBe(false);
|
||||
expect(list.addAt(100, 6)).toBe(false);
|
||||
});
|
||||
|
||||
it('should addBefore', () => {
|
||||
expect(list.addBefore(1, 0)).toBe(true);
|
||||
expect(list.addBefore(list.getNode(1)!, 2)).toBe(true);
|
||||
expect([...list]).toEqual([0, 2, 1, 2, 3, 4, 5]);
|
||||
});
|
||||
|
||||
it('should deleteAt', () => {
|
||||
expect(list.deleteAt(1)).toBeTruthy();
|
||||
expect(list.deleteAt(1)).toBe(true);
|
||||
expect(list.deleteAt(-1)).toBe(false);
|
||||
expect(list.deleteAt(list.size)).toBe(false);
|
||||
expect(list.size).toBe(4);
|
||||
expect(list.deleteAt(4)).toBe(false);
|
||||
expect([...list]).toEqual([1, 3, 4, 5]);
|
||||
expect(list.isEmpty()).toBe(false);
|
||||
expect(list.deleteAt(3)).toBe(true);
|
||||
expect([...list]).toEqual([1, 3, 4]);
|
||||
});
|
||||
|
||||
it('should delete tail', () => {
|
||||
|
@ -94,6 +107,13 @@ describe('DoublyLinkedList Operation Test', () => {
|
|||
expect(list.tail).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should initialize with toElementFn', () => {
|
||||
const dl = new DoublyLinkedList([{ key: 1 }, { key: 2 }, { key: 3 }], { toElementFn: ({ key }) => key });
|
||||
expect([...dl]).toEqual([1, 2, 3]);
|
||||
expect(dl.first).toBe(1);
|
||||
expect(dl.last).toBe(3);
|
||||
});
|
||||
|
||||
it('should push elements to the list', () => {
|
||||
list.push(1);
|
||||
list.push(2);
|
||||
|
@ -111,8 +131,13 @@ describe('DoublyLinkedList Operation Test', () => {
|
|||
expect(list.size).toBe(1);
|
||||
expect(list.head!.value).toBe(1);
|
||||
expect(list.tail!.value).toBe(1);
|
||||
list.pop();
|
||||
expect([...list]).toEqual([]);
|
||||
list.pop();
|
||||
expect([...list]).toEqual([]);
|
||||
});
|
||||
it('should insert elements at specific positions', () => {
|
||||
expect(list.at(0)).toBe(undefined);
|
||||
list.push(1);
|
||||
list.push(2);
|
||||
list.push(3);
|
||||
|
@ -134,6 +159,8 @@ describe('DoublyLinkedList Operation Test', () => {
|
|||
expect(list.size).toBe(6);
|
||||
expect(list.at(5)).toBe(4);
|
||||
expect(list.tail!.value).toBe(4);
|
||||
expect(list.at(-1)).toBe(undefined);
|
||||
expect(list.at(6)).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should delete elements at specific positions', () => {
|
||||
|
@ -445,9 +472,11 @@ describe('iterable methods', () => {
|
|||
expect(dl.reduce((accumulator, element) => accumulator + element, 0)).toEqual(6);
|
||||
});
|
||||
|
||||
test('values', () => {
|
||||
it('values', () => {
|
||||
const dl = new DoublyLinkedList<number>();
|
||||
dl.push(1);
|
||||
dl.shift();
|
||||
expect([...dl]).toEqual([]);
|
||||
dl.unshift(1);
|
||||
dl.push(2);
|
||||
dl.push(3);
|
||||
dl.delete(2);
|
||||
|
@ -458,7 +487,7 @@ describe('iterable methods', () => {
|
|||
expect([...dl.values()]).toEqual([3, 1]);
|
||||
});
|
||||
|
||||
test('some', () => {
|
||||
it('some', () => {
|
||||
const dl = new DoublyLinkedList<number>();
|
||||
dl.push(1);
|
||||
dl.push(2);
|
||||
|
|
|
@ -9,6 +9,16 @@ describe('SinglyLinkedListNode', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('SinglyLinkedList Initiate Test', () => {
|
||||
it('should initiate with toElementFn', () => {
|
||||
const sl = new SinglyLinkedList([{ key: 1 }, { key: 2 }, { key: 3 }, { key: 4 }, { key: 5 }], {
|
||||
toElementFn: ({ key }) => key
|
||||
});
|
||||
|
||||
expect([...sl]).toEqual([1, 2, 3, 4, 5]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SinglyLinkedList Operation Test', () => {
|
||||
let list: SinglyLinkedList<number>;
|
||||
let objectList: SinglyLinkedList<{
|
||||
|
@ -95,6 +105,10 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
list.push(3);
|
||||
list.addAfter(2, 4);
|
||||
expect(list.toArray()).toEqual([1, 2, 4, 3]);
|
||||
list.addAfter(list.getNode(2)!, 4);
|
||||
expect(list.toArray()).toEqual([1, 2, 4, 4, 3]);
|
||||
list.addAfter(list.getNode(3)!, 4);
|
||||
expect(list.toArray()).toEqual([1, 2, 4, 4, 3, 4]);
|
||||
});
|
||||
|
||||
it('should return false if the existing value is not found', () => {
|
||||
|
@ -132,12 +146,17 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
list.push(3);
|
||||
list.push(4);
|
||||
list.push(5);
|
||||
expect(list.delete(undefined)).toBe(false);
|
||||
expect(list.delete(2)).toBe(true);
|
||||
expect(list.toArray()).toEqual([1, 3, 4, 5]);
|
||||
expect(list.delete(1)).toBe(true);
|
||||
expect(list.toArray()).toEqual([3, 4, 5]);
|
||||
expect(list.delete(5)).toBe(true);
|
||||
expect(list.toArray()).toEqual([3, 4]);
|
||||
expect(list.delete(4)).toBe(true);
|
||||
expect(list.toArray()).toEqual([3]);
|
||||
expect(list.delete(3)).toBe(true);
|
||||
expect(list.toArray()).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return false if the value is not found', () => {
|
||||
|
@ -229,11 +248,14 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
|
||||
describe('addBefore', () => {
|
||||
it('should insert an element before an existing value', () => {
|
||||
expect(list.addBefore(2, 4)).toBe(false);
|
||||
list.push(1);
|
||||
list.push(2);
|
||||
list.push(3);
|
||||
list.addBefore(2, 4);
|
||||
expect(list.toArray()).toEqual([1, 4, 2, 3]);
|
||||
expect(list.addBefore(list.getNode(2)!, 4)).toBe(true);
|
||||
expect([...list]).toEqual([1, 4, 4, 2, 3]);
|
||||
});
|
||||
|
||||
it('should insert an element at the beginning', () => {
|
||||
|
@ -281,7 +303,11 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
it('should delete and return the first element', () => {
|
||||
list.push(1);
|
||||
list.push(2);
|
||||
expect(list.first).toBe(1);
|
||||
expect(list.last).toBe(2);
|
||||
const removed = list.deleteAt(0);
|
||||
expect(list.first).toBe(2);
|
||||
expect(list.last).toBe(2);
|
||||
expect(removed).toBe(true);
|
||||
expect(list.toArray()).toEqual([2]);
|
||||
});
|
||||
|
@ -321,6 +347,9 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
list.addAt(1, 3);
|
||||
list.addAt(1, 2);
|
||||
expect(list.toArray()).toEqual([1, 2, 3]);
|
||||
expect(list.addAt(5, 5)).toBe(false);
|
||||
expect(list.addAt(-1, -1)).toBe(false);
|
||||
expect(list.toArray()).toEqual([1, 2, 3]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -354,6 +383,7 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
|
||||
it('should clone', function () {
|
||||
const sList = new SinglyLinkedList<string>();
|
||||
sList.delete('1');
|
||||
sList.push('1');
|
||||
sList.push('6');
|
||||
sList.push('2');
|
||||
|
@ -367,6 +397,8 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
sList.delete('5');
|
||||
expect([...sList]).toEqual(['1', '6', '0', '9']);
|
||||
expect([...cloned]).toEqual(['1', '6', '0', '5', '9']);
|
||||
sList.delete(sList.getNode('0'));
|
||||
expect([...sList]).toEqual(['1', '6', '9']);
|
||||
});
|
||||
|
||||
describe('countOccurrences', () => {
|
||||
|
|
|
@ -22,6 +22,14 @@ describe('Matrix', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should initiate with empty', () => {
|
||||
matrix = new Matrix([], { rows: 2, cols: 2 });
|
||||
expect(matrix.data).toEqual([
|
||||
[0, 0],
|
||||
[0, 0]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should get a value at a specific position', () => {
|
||||
expect(matrix.get(1, 1)).toBe(0);
|
||||
expect(matrix.get(2, 2)).toBe(0);
|
||||
|
@ -213,7 +221,7 @@ describe('Matrix', () => {
|
|||
});
|
||||
|
||||
describe('transpose', () => {
|
||||
test('should transpose a matrix with numeric values correctly', () => {
|
||||
it('should transpose a matrix with numeric values correctly', () => {
|
||||
const originalMatrix = new Matrix([
|
||||
[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
|
@ -231,7 +239,7 @@ describe('Matrix', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should transpose an empty matrix correctly', () => {
|
||||
it('should transpose an empty matrix correctly', () => {
|
||||
const originalMatrix = new Matrix([]);
|
||||
|
||||
const transposedMatrix = originalMatrix.transpose();
|
||||
|
@ -241,7 +249,7 @@ describe('Matrix', () => {
|
|||
expect(transposedMatrix.data).toEqual([]);
|
||||
});
|
||||
|
||||
test('should throw an error when transposing a non-rectangular matrix', () => {
|
||||
it('should throw an error when transposing a non-rectangular matrix', () => {
|
||||
const originalMatrix = new Matrix([
|
||||
[1, 2, 3],
|
||||
[4, 5]
|
||||
|
@ -292,10 +300,32 @@ describe('Matrix', () => {
|
|||
[-0.046511627906976744, -0.023255813953488372, 0.23255813953488372]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should throw error when cols does not equal to rows', () => {
|
||||
const data: number[][] = [
|
||||
[4, 7, 2],
|
||||
[2, 6, 3]
|
||||
];
|
||||
|
||||
const matrix = new Matrix(data);
|
||||
expect(() => matrix.inverse()).toThrow('Matrix must be square for inversion.');
|
||||
});
|
||||
|
||||
it('should clone', () => {
|
||||
const data: number[][] = [
|
||||
[4, 7, 2],
|
||||
[2, 6, 3]
|
||||
];
|
||||
|
||||
const matrix = new Matrix(data);
|
||||
const cloned = matrix.clone();
|
||||
expect(cloned instanceof Matrix).toBe(true);
|
||||
expect(cloned.data).toEqual(data);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dot', () => {
|
||||
test('should calculate the dot product of two matrices', () => {
|
||||
it('should calculate the dot product of two matrices', () => {
|
||||
const matrix1 = new Matrix([
|
||||
[1, 2],
|
||||
[3, 4]
|
||||
|
@ -313,7 +343,7 @@ describe('Matrix', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should throw an error for incompatible matrices', () => {
|
||||
it('should throw an error for incompatible matrices', () => {
|
||||
const matrix1 = new Matrix([
|
||||
[1, 2],
|
||||
[3, 4]
|
||||
|
|
|
@ -129,4 +129,35 @@ describe('MaxPriorityQueue Operation Test', () => {
|
|||
|
||||
expect([...maxPQ.sort()]).toEqual([8, 7, 6, 5, 4, 3, 1]);
|
||||
});
|
||||
|
||||
it('should MaxPriorityQueue filter, map work well', function () {
|
||||
const minPQ2 = new MaxPriorityQueue<number>([]);
|
||||
minPQ2.refill([2, 5, 8, 1, 6, 7, 4]);
|
||||
|
||||
const cloned = minPQ2.clone();
|
||||
const filtered = cloned.filter(item => item % 2 === 1);
|
||||
expect(filtered instanceof MaxPriorityQueue).toBe(true);
|
||||
expect([...filtered]).toEqual([7, 1, 5]);
|
||||
|
||||
const mapped = filtered.map(
|
||||
item => ({ key: item }),
|
||||
(a, b) => b.key - a.key
|
||||
);
|
||||
expect(mapped instanceof MaxPriorityQueue).toBe(true);
|
||||
expect([...mapped]).toEqual([{ key: 7 }, { key: 1 }, { key: 5 }]);
|
||||
});
|
||||
|
||||
it('should MaxPriorityQueue throw an error while initialed with object data', function () {
|
||||
expect(() => {
|
||||
new MaxPriorityQueue<{ key: number }>([{ key: 7 }, { key: 1 }, { key: 7 }]);
|
||||
}).toThrow(
|
||||
"When comparing object types, a custom comparator must be defined in the constructor's options parameter."
|
||||
);
|
||||
});
|
||||
|
||||
it('should MaxPriorityQueue comparator return 0 when equal values are added', function () {
|
||||
const duplicated = new MaxPriorityQueue<number>([7, 1, 7, 7]);
|
||||
expect(duplicated.size).toBe(4);
|
||||
expect([...duplicated]).toEqual([7, 7, 7, 1]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -60,4 +60,21 @@ describe('MinPriorityQueue Operation Test', () => {
|
|||
const sortedArray = priorityQueue.sort();
|
||||
expect(sortedArray).toEqual([1, 3, 5, 7]);
|
||||
});
|
||||
|
||||
it('should MinPriorityQueue filter, map work well', function () {
|
||||
const minPQ2 = new MinPriorityQueue<number>([]);
|
||||
minPQ2.refill([2, 5, 8, 1, 6, 7, 4]);
|
||||
|
||||
const cloned = minPQ2.clone();
|
||||
const filtered = cloned.filter(item => item % 2 === 1);
|
||||
expect(filtered instanceof MinPriorityQueue).toBe(true);
|
||||
expect([...filtered]).toEqual([1, 5, 7]);
|
||||
|
||||
const mapped = filtered.map(
|
||||
item => ({ key: item }),
|
||||
(a, b) => a.key - b.key
|
||||
);
|
||||
expect(mapped instanceof MinPriorityQueue).toBe(true);
|
||||
expect([...mapped]).toEqual([{ key: 1 }, { key: 5 }, { key: 7 }]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -52,6 +52,23 @@ describe('PriorityQueue Operation Test', () => {
|
|||
expect(minPQ1.dfs('POST')).toEqual([4, 3, 5, 2, 8, 7, 6, 1]);
|
||||
expect(minPQ1.dfs('PRE')).toEqual([1, 2, 3, 4, 5, 6, 8, 7]);
|
||||
});
|
||||
|
||||
it('should PriorityQueue filter, map work well', function () {
|
||||
const minPQ2 = new PriorityQueue<number>([], {
|
||||
comparator: (a, b) => a - b
|
||||
});
|
||||
minPQ2.refill([2, 5, 8, 3, 1, 6, 7, 4]);
|
||||
const filtered = minPQ2.filter(item => item % 2 === 1);
|
||||
expect(filtered instanceof PriorityQueue).toBe(true);
|
||||
expect([...filtered]).toEqual([1, 3, 5, 7]);
|
||||
|
||||
const mapped = filtered.map(
|
||||
item => ({ key: item }),
|
||||
(a, b) => a.key - b.key
|
||||
);
|
||||
expect(mapped instanceof PriorityQueue).toBe(true);
|
||||
expect([...mapped]).toEqual([{ key: 1 }, { key: 3 }, { key: 5 }, { key: 7 }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Priority Queue Performance Test', () => {
|
||||
|
|
|
@ -10,19 +10,19 @@ describe('Deque - Basic Operations', () => {
|
|||
deque = new Deque<number>([1, 2]);
|
||||
});
|
||||
|
||||
test('push should add elements to the end', () => {
|
||||
it('push should add elements to the end', () => {
|
||||
expect(deque.size).toBe(2);
|
||||
expect(deque.last).toBe(2);
|
||||
});
|
||||
|
||||
test('pop should remove elements from the end', () => {
|
||||
it('pop should remove elements from the end', () => {
|
||||
expect(deque.pop()).toBe(2);
|
||||
expect(deque.size).toBe(1);
|
||||
expect(deque.pop()).toBe(1);
|
||||
expect(deque.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('unshift should add elements to the beginning', () => {
|
||||
it('unshift should add elements to the beginning', () => {
|
||||
deque.clear();
|
||||
deque.unshift(1);
|
||||
deque.unshift(2);
|
||||
|
@ -30,7 +30,7 @@ describe('Deque - Basic Operations', () => {
|
|||
expect(deque.first).toBe(2);
|
||||
});
|
||||
|
||||
test('shift should remove elements from the beginning', () => {
|
||||
it('shift should remove elements from the beginning', () => {
|
||||
deque.clear();
|
||||
deque.unshift(1);
|
||||
deque.unshift(2);
|
||||
|
@ -40,17 +40,17 @@ describe('Deque - Basic Operations', () => {
|
|||
expect(deque.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('at should retrieve the correct element', () => {
|
||||
it('at should retrieve the correct element', () => {
|
||||
expect(deque.at(0)).toBe(1);
|
||||
expect(deque.at(1)).toBe(2);
|
||||
});
|
||||
|
||||
test('setAt should set the correct element', () => {
|
||||
it('setAt should set the correct element', () => {
|
||||
deque.setAt(0, 3);
|
||||
expect(deque.at(0)).toBe(3);
|
||||
});
|
||||
|
||||
test('should at after shifting', () => {
|
||||
it('should at after shifting', () => {
|
||||
deque.clear();
|
||||
for (let i = 0; i < 100; i++) {
|
||||
deque.push(i);
|
||||
|
@ -65,7 +65,7 @@ describe('Deque - Basic Operations', () => {
|
|||
}
|
||||
});
|
||||
|
||||
test('should at after popping', () => {
|
||||
it('should at after popping', () => {
|
||||
deque.clear();
|
||||
for (let i = 0; i < 100; i++) {
|
||||
deque.push(i);
|
||||
|
@ -115,14 +115,14 @@ describe('Deque - Complex Operations', () => {
|
|||
deque = new Deque<number>();
|
||||
});
|
||||
|
||||
test('addAt should insert elements at the specified position', () => {
|
||||
deque.push(1);
|
||||
deque.push(3);
|
||||
it('addAt should insert elements at the specified position', () => {
|
||||
deque.addAt(0, 1);
|
||||
deque.addAt(1, 3);
|
||||
deque.addAt(1, 2);
|
||||
expect(deque.toArray()).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('cut should remove elements after the specified position', () => {
|
||||
it('cut should remove elements after the specified position', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
|
@ -136,9 +136,17 @@ describe('Deque - Complex Operations', () => {
|
|||
expect([...dq1.cut(3, true)]).toEqual([1, 2, 3, 4]);
|
||||
expect(dq1.size).toBe(4);
|
||||
expect([...dq1]).toEqual([1, 2, 3, 4]);
|
||||
const dqCut = dq1.cut(2);
|
||||
expect(dqCut.toArray()).toEqual([1, 2, 3]);
|
||||
const dqCutFromBeginning = dqCut.cut(0, true);
|
||||
expect(dqCutFromBeginning.toArray()).toEqual([1]);
|
||||
dqCutFromBeginning.cut(-1, true);
|
||||
expect(dqCutFromBeginning.toArray()).toEqual([]);
|
||||
const dqCutFromNegative = dqCutFromBeginning.cut(-1);
|
||||
expect([...dqCutFromNegative]).toEqual([]);
|
||||
});
|
||||
|
||||
test('cutRest should remove elements after the specified position', () => {
|
||||
it('cutRest should remove elements after the specified position', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
|
@ -160,17 +168,28 @@ describe('Deque - Complex Operations', () => {
|
|||
const dq1 = new Deque([1, 2, 3, 4, 5, 6, 7]);
|
||||
expect([...dq1.cutRest(3)]).toEqual([4, 5, 6, 7]);
|
||||
expect([...dq1]).toEqual([1, 2, 3, 4, 5, 6, 7]);
|
||||
const dq2 = dq1.cutRest(0, true);
|
||||
expect(dq2.toArray()).toEqual([1, 2, 3, 4, 5, 6, 7]);
|
||||
dq2.cutRest(-1, true);
|
||||
expect(dq2.toArray()).toEqual([1, 2, 3, 4, 5, 6, 7]);
|
||||
const dq3 = dq2.cutRest(-1);
|
||||
expect([...dq3]).toEqual([1, 2, 3, 4, 5, 6, 7]);
|
||||
});
|
||||
|
||||
test('deleteAt should remove the element at the specified position', () => {
|
||||
it('deleteAt should remove the element at the specified position', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
deque.deleteAt(1);
|
||||
expect(deque.toArray()).toEqual([1, 3]);
|
||||
deque.deleteAt(1);
|
||||
deque.deleteAt(0);
|
||||
expect(deque.toArray()).toEqual([]);
|
||||
});
|
||||
|
||||
test('delete should remove all instances of an element', () => {
|
||||
it('delete should remove all instances of an element', () => {
|
||||
deque.delete(2);
|
||||
expect(deque.toArray()).toEqual([]);
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(2);
|
||||
|
@ -179,7 +198,7 @@ describe('Deque - Complex Operations', () => {
|
|||
expect(deque.toArray()).toEqual([1, 3]);
|
||||
});
|
||||
|
||||
test('reverse should reverse the order of elements', () => {
|
||||
it('reverse should reverse the order of elements', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
|
@ -187,16 +206,19 @@ describe('Deque - Complex Operations', () => {
|
|||
expect(deque.toArray()).toEqual([3, 2, 1]);
|
||||
});
|
||||
|
||||
test('unique should remove duplicate elements', () => {
|
||||
it('unique should remove duplicate elements', () => {
|
||||
deque.push(1);
|
||||
const noNeedUnique = deque.unique();
|
||||
expect(noNeedUnique).toBe(deque);
|
||||
deque.push(2);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
deque.unique();
|
||||
const uniquer = deque.unique();
|
||||
expect(uniquer).toBe(deque);
|
||||
expect(deque.toArray()).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('sort should sort elements according to a comparator', () => {
|
||||
it('sort should sort elements according to a comparator', () => {
|
||||
deque.push(3);
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
|
@ -204,7 +226,43 @@ describe('Deque - Complex Operations', () => {
|
|||
expect([...deque]).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('shrinkToFit should reduce the memory footprint', () => {});
|
||||
it('shrinkToFit should reduce the memory footprint', () => {
|
||||
deque.shrinkToFit();
|
||||
expect(deque.size).toBe(0);
|
||||
expect(deque.has(1)).toBe(false);
|
||||
expect(deque.bucketFirst).toBe(0);
|
||||
expect(deque.bucketLast).toBe(0);
|
||||
expect(deque.firstInBucket).toBe(2048);
|
||||
expect(deque.lastInBucket).toBe(2048);
|
||||
expect(deque.bucketCount).toBe(1);
|
||||
expect(deque.buckets[0][0]).toEqual(undefined);
|
||||
expect(deque.buckets.length).toEqual(1);
|
||||
deque.push(1);
|
||||
deque.shrinkToFit();
|
||||
|
||||
deque = new Deque([1, 2, 3, 4, 5], { bucketSize: 2 });
|
||||
expect(deque.size).toBe(5);
|
||||
expect(deque.has(1)).toBe(true);
|
||||
expect(deque.bucketFirst).toBe(0);
|
||||
expect(deque.bucketLast).toBe(2);
|
||||
expect(deque.firstInBucket).toBe(0);
|
||||
expect(deque.lastInBucket).toBe(0);
|
||||
expect(deque.bucketCount).toBe(3);
|
||||
expect(deque.buckets[0][0]).toBe(1);
|
||||
expect(deque.buckets[2][0]).toBe(5);
|
||||
expect(deque.buckets.length).toBe(3);
|
||||
deque.shrinkToFit();
|
||||
expect(deque.buckets).toEqual([[1, 2], [3, 4], [5]]);
|
||||
deque.push(6);
|
||||
deque.push(7);
|
||||
deque.shrinkToFit();
|
||||
expect(deque.buckets).toEqual([
|
||||
[1, 2],
|
||||
[3, 4],
|
||||
[5, 6],
|
||||
[7, 2]
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('Deque - Utility Operations', () => {
|
||||
let deque: Deque<number>;
|
||||
|
@ -213,7 +271,8 @@ describe('Deque - Utility Operations', () => {
|
|||
deque = new Deque<number>();
|
||||
});
|
||||
|
||||
test('find should return the first element that matches the condition', () => {
|
||||
it('find should return the first element that matches the condition', () => {
|
||||
expect(deque.first).toBe(undefined);
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
|
@ -221,22 +280,23 @@ describe('Deque - Utility Operations', () => {
|
|||
expect(found).toBe(2);
|
||||
});
|
||||
|
||||
test('indexOf should return the index of the first occurrence of an element', () => {
|
||||
it('indexOf should return the index of the first occurrence of an element', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
const index = deque.indexOf(2);
|
||||
expect(index).toBe(1);
|
||||
expect(deque.indexOf(4)).toBe(-1);
|
||||
});
|
||||
|
||||
test('toArray should convert the deque to an array', () => {
|
||||
it('toArray should convert the deque to an array', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
expect(deque.toArray()).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('filter should filter elements based on a predicate', () => {
|
||||
it('filter should filter elements based on a predicate', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
|
@ -244,7 +304,7 @@ describe('Deque - Utility Operations', () => {
|
|||
expect(filtered.toArray()).toEqual([2, 3]);
|
||||
});
|
||||
|
||||
test('map should apply a function to all elements', () => {
|
||||
it('map should apply a function to all elements', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
|
@ -252,7 +312,7 @@ describe('Deque - Utility Operations', () => {
|
|||
expect(mapped.toArray()).toEqual([2, 4, 6]);
|
||||
});
|
||||
|
||||
test('print should print the deque elements', () => {
|
||||
it('print should print the deque elements', () => {
|
||||
// const consoleSpy = jest.spyOn(console, 'log');
|
||||
// deque.push(1);
|
||||
// deque.push(2);
|
||||
|
@ -260,7 +320,7 @@ describe('Deque - Utility Operations', () => {
|
|||
// expect(consoleSpy).toHaveBeenCalledWith([1, 2]);
|
||||
});
|
||||
|
||||
test('should maxLen work well', () => {
|
||||
it('should maxLen work well', () => {
|
||||
const dequeMaxLen = new Deque([3, 4, 5, 6, 7], { maxLen: 3 });
|
||||
expect(dequeMaxLen.size).toBe(3);
|
||||
expect(dequeMaxLen.toArray()).toEqual([5, 6, 7]);
|
||||
|
@ -286,42 +346,43 @@ describe('Deque - Additional Operations', () => {
|
|||
deque = new Deque<number>();
|
||||
});
|
||||
|
||||
test('push should add an element to the end', () => {
|
||||
it('push should add an element to the end', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
expect(deque.last).toBe(2);
|
||||
expect(deque.size).toBe(2);
|
||||
});
|
||||
|
||||
test('pop should remove and return the last element', () => {
|
||||
it('pop should remove and return the last element', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
expect(deque.pop()).toBe(2);
|
||||
expect(deque.size).toBe(1);
|
||||
});
|
||||
|
||||
test('unshift should add an element to the beginning', () => {
|
||||
it('unshift should add an element to the beginning', () => {
|
||||
deque.unshift(1);
|
||||
deque.unshift(2);
|
||||
expect(deque.first).toBe(2);
|
||||
expect(deque.size).toBe(2);
|
||||
});
|
||||
|
||||
test('shift should remove and return the first element', () => {
|
||||
it('shift should remove and return the first element', () => {
|
||||
deque.shift();
|
||||
deque.unshift(1);
|
||||
deque.unshift(2);
|
||||
expect(deque.shift()).toBe(2);
|
||||
expect(deque.size).toBe(1);
|
||||
});
|
||||
|
||||
test('clear should reset the deque', () => {
|
||||
it('clear should reset the deque', () => {
|
||||
deque.unshift(1);
|
||||
deque.clear();
|
||||
expect(deque.size).toBe(0);
|
||||
expect(deque.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('begin should yield elements from the beginning', () => {
|
||||
it('begin should yield elements from the beginning', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
const iterator = deque.begin();
|
||||
|
@ -329,7 +390,7 @@ describe('Deque - Additional Operations', () => {
|
|||
expect(iterator.next().value).toBe(2);
|
||||
});
|
||||
|
||||
test('reverseBegin should yield elements in reverse order', () => {
|
||||
it('reverseBegin should yield elements in reverse order', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
const iterator = deque.reverseBegin();
|
||||
|
@ -347,13 +408,13 @@ describe('Deque - push Method', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('push should add an element when deque is empty', () => {
|
||||
it('push should add an element when deque is empty', () => {
|
||||
deque.push(1);
|
||||
expect(deque.last).toBe(1);
|
||||
expect(deque.size).toBe(1);
|
||||
});
|
||||
|
||||
test('push should add an element when lastInBucket is not at max', () => {
|
||||
it('push should add an element when lastInBucket is not at max', () => {
|
||||
for (let i = 0; i < bucketSize - 1; i++) {
|
||||
deque.push(i);
|
||||
}
|
||||
|
@ -362,7 +423,7 @@ describe('Deque - push Method', () => {
|
|||
expect(deque.size).toBe(bucketSize);
|
||||
});
|
||||
|
||||
test('push should add an element and move to next bucket when last bucket is full', () => {
|
||||
it('push should add an element and move to next bucket when last bucket is full', () => {
|
||||
for (let i = 0; i < bucketSize; i++) {
|
||||
deque.push(i);
|
||||
}
|
||||
|
@ -371,7 +432,7 @@ describe('Deque - push Method', () => {
|
|||
expect(deque.size).toBe(bucketSize + 1);
|
||||
});
|
||||
|
||||
test('push should add an element and reallocate when last bucket and lastInBucket are at max', () => {
|
||||
it('push should add an element and reallocate when last bucket and lastInBucket are at max', () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
deque.push(i);
|
||||
}
|
||||
|
@ -391,20 +452,20 @@ describe('Deque - pop Method', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('pop should remove and return the last element', () => {
|
||||
it('pop should remove and return the last element', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
expect(deque.pop()).toBe(2);
|
||||
expect(deque.size).toBe(1);
|
||||
});
|
||||
|
||||
test('pop should handle popping the only element', () => {
|
||||
it('pop should handle popping the only element', () => {
|
||||
deque.push(1);
|
||||
expect(deque.pop()).toBe(1);
|
||||
expect(deque.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('pop should adjust bucketLast and lastInBucket correctly', () => {
|
||||
it('pop should adjust bucketLast and lastInBucket correctly', () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
deque.push(i);
|
||||
}
|
||||
|
@ -424,13 +485,13 @@ describe('Deque - unshift Method', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('unshift should add an element to the beginning when deque is empty', () => {
|
||||
it('unshift should add an element to the beginning when deque is empty', () => {
|
||||
deque.unshift(1);
|
||||
expect(deque.first).toBe(1);
|
||||
expect(deque.size).toBe(1);
|
||||
});
|
||||
|
||||
test('unshift should add an element to the beginning and adjust firstInBucket', () => {
|
||||
it('unshift should add an element to the beginning and adjust firstInBucket', () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
deque.unshift(i);
|
||||
}
|
||||
|
@ -439,7 +500,7 @@ describe('Deque - unshift Method', () => {
|
|||
expect(deque.first).toBe(0);
|
||||
});
|
||||
|
||||
test('unshift should add an element and reallocate when needed', () => {
|
||||
it('unshift should add an element and reallocate when needed', () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
deque.unshift(i);
|
||||
}
|
||||
|
@ -458,20 +519,20 @@ describe('Deque - shift Method', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('shift should remove and return the first element', () => {
|
||||
it('shift should remove and return the first element', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
expect(deque.shift()).toBe(1);
|
||||
expect(deque.size).toBe(1);
|
||||
});
|
||||
|
||||
test('shift should handle shifting the only element', () => {
|
||||
it('shift should handle shifting the only element', () => {
|
||||
deque.push(1);
|
||||
expect(deque.shift()).toBe(1);
|
||||
expect(deque.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('shift should adjust bucketFirst and firstInBucket correctly', () => {
|
||||
it('shift should adjust bucketFirst and firstInBucket correctly', () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
deque.push(i);
|
||||
}
|
||||
|
@ -481,3 +542,183 @@ describe('Deque - shift Method', () => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Deque', () => {
|
||||
it('should initialize with default iterable with length function', () => {
|
||||
class IterableNumbers {
|
||||
private readonly _elements: number[] = [];
|
||||
|
||||
constructor(elements: number[]) {
|
||||
this._elements = elements;
|
||||
}
|
||||
|
||||
*[Symbol.iterator]() {
|
||||
for (let i = 0; i < this._elements.length; ++i) {
|
||||
yield this._elements[i];
|
||||
}
|
||||
}
|
||||
|
||||
length() {
|
||||
return this._elements.length;
|
||||
}
|
||||
}
|
||||
|
||||
const numbers = new IterableNumbers([1, 6, 7, 3, 2, 4, 5]);
|
||||
const deque = new Deque(numbers, { bucketSize: 3 });
|
||||
expect(deque.size).toBe(7);
|
||||
expect(deque.bucketSize).toBe(3);
|
||||
expect(deque.maxLen).toBe(-1);
|
||||
});
|
||||
|
||||
it('should initialize with default iterable with size function', () => {
|
||||
class IterableNumbersWithSize {
|
||||
private readonly _elements: number[] = [];
|
||||
|
||||
constructor(elements: number[]) {
|
||||
this._elements = elements;
|
||||
}
|
||||
|
||||
*[Symbol.iterator]() {
|
||||
for (let i = 0; i < this._elements.length; ++i) {
|
||||
yield this._elements[i];
|
||||
}
|
||||
}
|
||||
|
||||
size() {
|
||||
return this._elements.length;
|
||||
}
|
||||
}
|
||||
|
||||
const numbers = new IterableNumbersWithSize([1, 6, 7, 3, 2, 4, 5]);
|
||||
const deque = new Deque(numbers, { bucketSize: 3 });
|
||||
expect(deque.size).toBe(7);
|
||||
expect(deque.bucketSize).toBe(3);
|
||||
expect(deque.maxLen).toBe(-1);
|
||||
});
|
||||
|
||||
it('should initialize via toElementFn', () => {
|
||||
const objArr: Array<{
|
||||
key: number;
|
||||
}> = [{ key: 1 }, { key: 6 }, { key: 7 }, { key: 3 }, { key: 2 }, { key: 4 }, { key: 5 }];
|
||||
const deque = new Deque<number>(objArr, { toElementFn: item => item.key });
|
||||
expect(deque.size).toBe(7);
|
||||
expect(deque.has(1)).toBe(true);
|
||||
expect(deque.has(7)).toBe(true);
|
||||
expect(deque.has(8)).toBe(false);
|
||||
});
|
||||
|
||||
it('should bucket properties are correct', () => {
|
||||
const objArr: Array<{
|
||||
key: number;
|
||||
}> = [{ key: 1 }, { key: 6 }, { key: 7 }, { key: 3 }, { key: 2 }, { key: 4 }, { key: 5 }];
|
||||
const deque = new Deque<number>(objArr, { toElementFn: item => item.key, bucketSize: 3 });
|
||||
expect(deque.size).toBe(7);
|
||||
expect(deque.has(1)).toBe(true);
|
||||
expect(deque.bucketFirst).toBe(0);
|
||||
expect(deque.bucketLast).toBe(2);
|
||||
expect(deque.firstInBucket).toBe(1);
|
||||
expect(deque.lastInBucket).toBe(1); // TODO may be a problem
|
||||
expect(deque.bucketCount).toBe(3);
|
||||
expect(deque.buckets).toEqual([
|
||||
[, 1, 6],
|
||||
[7, 3, 2],
|
||||
[4, 5]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should pop work well when bucket boundary is reached', () => {
|
||||
const deque = new Deque<number>([1, 6, 7, 3, 2, 4, 5], { bucketSize: 3 });
|
||||
expect(deque.size).toBe(7);
|
||||
expect(deque.has(1)).toBe(true);
|
||||
expect(deque.bucketFirst).toBe(0);
|
||||
expect(deque.bucketLast).toBe(2);
|
||||
expect(deque.firstInBucket).toBe(1);
|
||||
expect(deque.lastInBucket).toBe(1); // TODO may be a problem
|
||||
expect(deque.bucketCount).toBe(3);
|
||||
expect(deque.buckets).toEqual([
|
||||
[, 1, 6],
|
||||
[7, 3, 2],
|
||||
[4, 5]
|
||||
]);
|
||||
for (let i = 0; i < 3; ++i) deque.pop();
|
||||
expect(deque.size).toBe(4);
|
||||
expect(deque.has(1)).toBe(true);
|
||||
expect(deque.bucketFirst).toBe(0);
|
||||
expect(deque.bucketLast).toBe(1);
|
||||
expect(deque.firstInBucket).toBe(1);
|
||||
expect(deque.lastInBucket).toBe(1);
|
||||
expect(deque.bucketCount).toBe(3);
|
||||
expect(deque.buckets).toEqual([
|
||||
[, 1, 6],
|
||||
[7, 3, 2],
|
||||
[4, 5]
|
||||
]); // TODO may be a problem
|
||||
deque.pop();
|
||||
expect(deque.size).toBe(3);
|
||||
expect(deque.has(1)).toBe(true);
|
||||
expect(deque.bucketFirst).toBe(0);
|
||||
expect(deque.bucketLast).toBe(1);
|
||||
expect(deque.firstInBucket).toBe(1);
|
||||
expect(deque.lastInBucket).toBe(0);
|
||||
expect(deque.bucketCount).toBe(3);
|
||||
expect(deque.buckets).toEqual([
|
||||
[, 1, 6],
|
||||
[7, 3, 2],
|
||||
[4, 5]
|
||||
]); // TODO may be a problem
|
||||
});
|
||||
|
||||
it('should shift work well when bucket boundary is reached and should shrinkToFit', () => {
|
||||
const deque = new Deque<number>([1, 6, 7, 3, 2, 4, 5], { bucketSize: 3 });
|
||||
expect(deque.size).toBe(7);
|
||||
expect(deque.has(1)).toBe(true);
|
||||
expect(deque.bucketFirst).toBe(0);
|
||||
expect(deque.bucketLast).toBe(2);
|
||||
expect(deque.firstInBucket).toBe(1);
|
||||
expect(deque.lastInBucket).toBe(1); // TODO may be a problem
|
||||
expect(deque.bucketCount).toBe(3);
|
||||
expect(deque.buckets).toEqual([
|
||||
[, 1, 6],
|
||||
[7, 3, 2],
|
||||
[4, 5]
|
||||
]);
|
||||
for (let i = 0; i < 3; ++i) deque.shift();
|
||||
expect(deque.size).toBe(4);
|
||||
expect(deque.has(1)).toBe(false);
|
||||
expect(deque.bucketFirst).toBe(1);
|
||||
expect(deque.bucketLast).toBe(2);
|
||||
expect(deque.firstInBucket).toBe(1);
|
||||
expect(deque.lastInBucket).toBe(1);
|
||||
expect(deque.bucketCount).toBe(3);
|
||||
expect(deque.buckets).toEqual([
|
||||
[, 1, 6],
|
||||
[7, 3, 2],
|
||||
[4, 5]
|
||||
]); // TODO may be a problem
|
||||
deque.shift();
|
||||
expect(deque.size).toBe(3);
|
||||
expect(deque.has(1)).toBe(false);
|
||||
expect(deque.bucketFirst).toBe(1);
|
||||
expect(deque.bucketLast).toBe(2);
|
||||
expect(deque.firstInBucket).toBe(2);
|
||||
expect(deque.lastInBucket).toBe(1);
|
||||
expect(deque.bucketCount).toBe(3);
|
||||
expect(deque.buckets).toEqual([
|
||||
[, 1, 6],
|
||||
[7, 3, 2],
|
||||
[4, 5]
|
||||
]); // TODO may be a problem
|
||||
deque.shrinkToFit();
|
||||
expect(deque.size).toBe(3);
|
||||
expect(deque.has(1)).toBe(false);
|
||||
expect(deque.bucketFirst).toBe(0);
|
||||
expect(deque.bucketLast).toBe(1);
|
||||
expect(deque.firstInBucket).toBe(2);
|
||||
expect(deque.lastInBucket).toBe(1);
|
||||
expect(deque.bucketCount).toBe(3);
|
||||
expect(deque.buckets).toEqual([
|
||||
[7, 3, 2],
|
||||
[4, 5]
|
||||
]); // TODO may be a problem
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,68 +10,68 @@ describe('Queue', () => {
|
|||
queue = new Queue<number>();
|
||||
});
|
||||
|
||||
test('new Queue() should create an empty queue', () => {
|
||||
it('new Queue() should create an empty queue', () => {
|
||||
expect(queue.size).toBe(0);
|
||||
expect(queue.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('push should add elements to the queue', () => {
|
||||
it('push should add elements to the queue', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
expect(queue.size).toBe(2);
|
||||
});
|
||||
|
||||
test('shift should remove the first element', () => {
|
||||
it('shift should remove the first element', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
expect(queue.shift()).toBe(1);
|
||||
expect(queue.size).toBe(1);
|
||||
});
|
||||
|
||||
test('shift should return undefined if queue is empty', () => {
|
||||
it('shift should return undefined if queue is empty', () => {
|
||||
expect(queue.shift()).toBeUndefined();
|
||||
});
|
||||
|
||||
test('first should return the first element without removing it', () => {
|
||||
it('first should return the first element without removing it', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
expect(queue.first).toBe(1);
|
||||
expect(queue.size).toBe(2);
|
||||
});
|
||||
|
||||
test('first should return undefined if queue is empty', () => {
|
||||
it('first should return undefined if queue is empty', () => {
|
||||
expect(queue.first).toBeUndefined();
|
||||
});
|
||||
|
||||
test('size should return the number of elements', () => {
|
||||
it('size should return the number of elements', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
expect(queue.size).toBe(2);
|
||||
});
|
||||
|
||||
test('isEmpty should return true if the queue is empty', () => {
|
||||
it('isEmpty should return true if the queue is empty', () => {
|
||||
expect(queue.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('isEmpty should return false if the queue is not empty', () => {
|
||||
it('isEmpty should return false if the queue is not empty', () => {
|
||||
queue.push(1);
|
||||
expect(queue.isEmpty()).toBeFalsy();
|
||||
});
|
||||
|
||||
test('toArray should return an array of queue elements', () => {
|
||||
it('toArray should return an array of queue elements', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
expect(queue.toArray()).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
test('clear should remove all elements from the queue', () => {
|
||||
it('clear should remove all elements from the queue', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
queue.clear();
|
||||
expect(queue.size).toBe(0);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
it('forEach should iterate over all elements', () => {
|
||||
const arr: number[] = [];
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
|
@ -80,7 +80,7 @@ describe('Queue', () => {
|
|||
});
|
||||
|
||||
// Boundary value testing
|
||||
test('push and shift with many elements', () => {
|
||||
it('push and shift with many elements', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
queue.push(i);
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ describe('Queue', () => {
|
|||
expect(queue.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('compact method should work well', () => {
|
||||
it('compact method should work well', () => {
|
||||
for (let i = 0; i < 1000; i++) queue.push(i);
|
||||
|
||||
for (let i = 0; i < 499; i++) queue.shift();
|
||||
|
@ -100,7 +100,7 @@ describe('Queue', () => {
|
|||
expect(queue.elements.length).toBe(501);
|
||||
});
|
||||
|
||||
test('should at after shifting', () => {
|
||||
it('should at after shifting', () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
queue.push(i);
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ describe('Queue', () => {
|
|||
}
|
||||
});
|
||||
|
||||
test('should toElementFn', () => {
|
||||
it('should toElementFn', () => {
|
||||
const queue = new Queue<string, { id: string }>([{ id: '1' }, { id: '5' }, { id: '3' }, { id: '4' }, { id: '2' }], {
|
||||
toElementFn: rawElement => rawElement.id
|
||||
});
|
||||
|
@ -177,6 +177,29 @@ describe('Queue', () => {
|
|||
expect([...queue]).toEqual(['1', '6', '9']);
|
||||
expect([...cloned]).toEqual(['1', '6', '0', '5', '9']);
|
||||
});
|
||||
|
||||
it('should set autoCompactRatio', function () {
|
||||
const queue = new Queue<number>();
|
||||
|
||||
queue.autoCompactRatio = 0.3;
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
queue.push(3);
|
||||
queue.push(4);
|
||||
queue.push(5);
|
||||
queue.push(6);
|
||||
queue.push(7);
|
||||
queue.push(8);
|
||||
queue.push(9);
|
||||
queue.push(10);
|
||||
expect(queue.elements.length).toBe(10);
|
||||
while (queue.size > 7) queue.shift();
|
||||
expect(queue.size).toBe(7);
|
||||
expect(queue.elements.length).toBe(10);
|
||||
queue.shift();
|
||||
expect(queue.size).toBe(6);
|
||||
expect(queue.elements.length).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Queue - Advanced Methods', () => {
|
||||
|
@ -186,7 +209,7 @@ describe('Queue - Advanced Methods', () => {
|
|||
queue = new Queue<number>();
|
||||
});
|
||||
|
||||
test('reduce should apply a function against an accumulator and each element', () => {
|
||||
it('reduce should apply a function against an accumulator and each element', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
queue.push(3);
|
||||
|
@ -194,13 +217,13 @@ describe('Queue - Advanced Methods', () => {
|
|||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('reduce should return initial value for empty queue', () => {
|
||||
it('reduce should return initial value for empty queue', () => {
|
||||
const initialValue = 0;
|
||||
const sum = queue.reduce((acc, val) => acc + val, initialValue);
|
||||
expect(sum).toBe(initialValue);
|
||||
});
|
||||
|
||||
test('filter should return a new queue with all elements that pass the test implemented by provided function', () => {
|
||||
it('filter should return a new queue with all elements that pass the test implemented by provided function', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
queue.push(3);
|
||||
|
@ -208,12 +231,12 @@ describe('Queue - Advanced Methods', () => {
|
|||
expect(filteredQueue.toArray()).toEqual([2, 3]);
|
||||
});
|
||||
|
||||
test('filter should return an empty queue for empty queue', () => {
|
||||
it('filter should return an empty queue for empty queue', () => {
|
||||
const filteredQueue = queue.filter(val => val > 1);
|
||||
expect(filteredQueue.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('map should create a new queue with the results of calling a provided function on every element', () => {
|
||||
it('map should create a new queue with the results of calling a provided function on every element', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
queue.push(3);
|
||||
|
@ -221,7 +244,7 @@ describe('Queue - Advanced Methods', () => {
|
|||
expect(mappedQueue.toArray()).toEqual([2, 4, 6]);
|
||||
});
|
||||
|
||||
test('map should return an empty queue for empty queue', () => {
|
||||
it('map should return an empty queue for empty queue', () => {
|
||||
const mappedQueue = queue.map(val => val * 2);
|
||||
expect(mappedQueue.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
@ -233,31 +256,31 @@ describe('Queue - Additional Methods', () => {
|
|||
queue = new Queue<number>();
|
||||
});
|
||||
|
||||
test('peekLast should return the last element without removing it', () => {
|
||||
it('peekLast should return the last element without removing it', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
expect(queue.last).toBe(2);
|
||||
expect(queue.size).toBe(2);
|
||||
});
|
||||
|
||||
test('peekLast should return undefined if queue is empty', () => {
|
||||
it('peekLast should return undefined if queue is empty', () => {
|
||||
expect(queue.last).toBeUndefined();
|
||||
});
|
||||
|
||||
test('at should return the element at the specified index', () => {
|
||||
it('at should return the element at the specified index', () => {
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
queue.push(3);
|
||||
expect(queue.at(1)).toBe(2);
|
||||
});
|
||||
|
||||
test('at should return undefined for an invalid index', () => {
|
||||
it('at should return undefined for an invalid index', () => {
|
||||
queue.push(1);
|
||||
expect(queue.at(3)).toBeUndefined();
|
||||
expect(queue.at(-1)).toBeUndefined();
|
||||
});
|
||||
|
||||
test('print should not throw any errors', () => {
|
||||
it('print should not throw any errors', () => {
|
||||
expect(() => {
|
||||
queue.push(1);
|
||||
// queue.print();
|
||||
|
@ -266,19 +289,19 @@ describe('Queue - Additional Methods', () => {
|
|||
});
|
||||
|
||||
describe('Queue - Static and Clone Methods', () => {
|
||||
test('fromArray should create a new queue from an array', () => {
|
||||
it('fromArray should create a new queue from an array', () => {
|
||||
const array = [1, 2, 3];
|
||||
const queue = Queue.fromArray(array);
|
||||
expect(queue.toArray()).toEqual(array);
|
||||
expect(queue.size).toBe(array.length);
|
||||
});
|
||||
|
||||
test('fromArray should create an empty queue from an empty array', () => {
|
||||
it('fromArray should create an empty queue from an empty array', () => {
|
||||
const queue = Queue.fromArray([]);
|
||||
expect(queue.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('clone should create a new queue with the same elements', () => {
|
||||
it('clone should create a new queue with the same elements', () => {
|
||||
const originalQueue = new Queue<number>();
|
||||
originalQueue.push(1);
|
||||
originalQueue.push(2);
|
||||
|
@ -288,7 +311,7 @@ describe('Queue - Static and Clone Methods', () => {
|
|||
expect(clonedQueue.size).toBe(originalQueue.size);
|
||||
});
|
||||
|
||||
test('clone should not affect the original queue when mutated', () => {
|
||||
it('clone should not affect the original queue when mutated', () => {
|
||||
const originalQueue = new Queue<number>();
|
||||
originalQueue.push(1);
|
||||
originalQueue.push(2);
|
||||
|
@ -306,18 +329,16 @@ describe('LinkedListQueue', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
queue = new LinkedListQueue<string>();
|
||||
queue.push('A');
|
||||
queue.push('B');
|
||||
});
|
||||
|
||||
it('should push elements to the end of the queue', () => {
|
||||
queue.push('A');
|
||||
queue.push('B');
|
||||
expect(queue.first).toBe('A');
|
||||
expect(queue.size).toBe(2);
|
||||
});
|
||||
|
||||
it('should shift elements from the front of the queue', () => {
|
||||
queue.push('A');
|
||||
queue.push('B');
|
||||
const dequeued = queue.shift();
|
||||
expect(dequeued).toBe('A');
|
||||
expect(queue.first).toBe('B');
|
||||
|
@ -325,8 +346,12 @@ describe('LinkedListQueue', () => {
|
|||
});
|
||||
|
||||
it('should peek at the front of the queue', () => {
|
||||
queue.push('A');
|
||||
queue.push('B');
|
||||
expect(queue.first).toBe('A');
|
||||
});
|
||||
|
||||
it('should clone method work correctly', () => {
|
||||
const cloned = queue.clone();
|
||||
expect(cloned instanceof LinkedListQueue).toBe(true);
|
||||
expect(cloned.size).toBe(2);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -19,6 +19,7 @@ describe('Stack', () => {
|
|||
});
|
||||
|
||||
it('should peek at the top element without removing it', () => {
|
||||
expect(stack.peek()).toBe(undefined);
|
||||
stack.push(1);
|
||||
stack.push(2);
|
||||
stack.push(3);
|
||||
|
@ -93,7 +94,7 @@ describe('Stack iterative methods', () => {
|
|||
stack.push(3);
|
||||
});
|
||||
|
||||
test('should iterate through the stack', () => {
|
||||
it('should iterate through the stack', () => {
|
||||
const result: number[] = [];
|
||||
for (const element of stack) {
|
||||
result.push(element);
|
||||
|
@ -102,7 +103,7 @@ describe('Stack iterative methods', () => {
|
|||
expect(result).toEqual([1, 2, 3]); // iteration should start from the top of the stack
|
||||
});
|
||||
|
||||
test('should apply forEach to the stack', () => {
|
||||
it('should apply forEach to the stack', () => {
|
||||
const result: number[] = [];
|
||||
stack.forEach(element => {
|
||||
result.push(element);
|
||||
|
@ -111,23 +112,36 @@ describe('Stack iterative methods', () => {
|
|||
expect(result).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('should filter elements in the stack', () => {
|
||||
it('should filter elements in the stack', () => {
|
||||
const filteredStack = stack.filter(element => element > 1);
|
||||
|
||||
expect(filteredStack.size).toBe(2);
|
||||
expect([...filteredStack]).toEqual([2, 3]);
|
||||
});
|
||||
|
||||
test('should map elements in the stack', () => {
|
||||
it('should map elements in the stack', () => {
|
||||
const mappedStack = stack.map(element => element * 2);
|
||||
|
||||
expect(mappedStack.size).toBe(3);
|
||||
expect([...mappedStack]).toEqual([2, 4, 6]);
|
||||
});
|
||||
|
||||
test('should reduce elements in the stack', () => {
|
||||
it('should reduce elements in the stack', () => {
|
||||
const sum = stack.reduce((accumulator, element) => accumulator + element, 0);
|
||||
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
it('should toElementFn', () => {
|
||||
const stack = new Stack([{ key: 1 }, { key: 2 }, { key: 5 }, { key: 3 }], { toElementFn: item => item.key });
|
||||
expect(stack.size).toBe(4);
|
||||
expect([...stack]).toEqual([1, 2, 5, 3]);
|
||||
});
|
||||
|
||||
it('should fromArray', () => {
|
||||
const stack = Stack.fromArray([1, 2, 5, 3]);
|
||||
expect(stack instanceof Stack).toBe(true);
|
||||
expect(stack.size).toBe(4);
|
||||
expect([...stack]).toEqual([1, 2, 5, 3]);
|
||||
});
|
||||
});
|
||||
|
|
58
test/unit/data-structures/tree/tree.test.ts
Normal file
58
test/unit/data-structures/tree/tree.test.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import { TreeNode } from '../../../../src';
|
||||
|
||||
describe('TreeNode', () => {
|
||||
it('should create a tree node with key and value', () => {
|
||||
const node = new TreeNode<string>('root', 'RootValue');
|
||||
expect(node.key).toBe('root');
|
||||
expect(node.value).toBe('RootValue');
|
||||
expect(node.children).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('should allow setting and getting key and value', () => {
|
||||
const node = new TreeNode<string>('node1', 'Value1');
|
||||
node.key = 'newKey';
|
||||
node.value = 'newValue';
|
||||
expect(node.key).toBe('newKey');
|
||||
expect(node.value).toBe('newValue');
|
||||
});
|
||||
|
||||
it('should add a single child node', () => {
|
||||
const parent = new TreeNode<string>('parent');
|
||||
const child = new TreeNode<string>('child', 'ChildValue');
|
||||
|
||||
parent.addChildren(child);
|
||||
|
||||
expect(parent.children).toHaveLength(1);
|
||||
expect(parent.children?.[0].key).toBe('child');
|
||||
expect(parent.children?.[0].value).toBe('ChildValue');
|
||||
});
|
||||
|
||||
it('should add multiple children nodes', () => {
|
||||
const parent = new TreeNode<string>('parent');
|
||||
const child1 = new TreeNode<string>('child1');
|
||||
const child2 = new TreeNode<string>('child2');
|
||||
|
||||
parent.addChildren([child1, child2]);
|
||||
|
||||
expect(parent.children).toHaveLength(2);
|
||||
expect(parent.children?.[0].key).toBe('child1');
|
||||
expect(parent.children?.[1].key).toBe('child2');
|
||||
parent.children = [];
|
||||
|
||||
expect(parent.children[0]).toBe(undefined);
|
||||
expect(parent.children[1]).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should calculate the correct height of the tree', () => {
|
||||
const root = new TreeNode<string>('root');
|
||||
const child1 = new TreeNode<string>('child1');
|
||||
const child2 = new TreeNode<string>('child2');
|
||||
const grandChild = new TreeNode<string>('grandChild');
|
||||
|
||||
root.addChildren(child1);
|
||||
root.addChildren(child2);
|
||||
child1.addChildren(grandChild);
|
||||
|
||||
expect(root.getHeight()).toBe(2); // root -> child1 -> grandChild (height = 2)
|
||||
});
|
||||
});
|
|
@ -22,6 +22,31 @@ describe('TrieNode', () => {
|
|||
node.isEnd = true;
|
||||
expect(node.isEnd).toBe(true);
|
||||
});
|
||||
|
||||
it('should set key property correctly', () => {
|
||||
const node = new TrieNode('a');
|
||||
node.isEnd = false;
|
||||
expect(node).toEqual({
|
||||
_children: new Map(),
|
||||
_isEnd: false,
|
||||
_key: 'a'
|
||||
});
|
||||
node.key = 'b';
|
||||
expect(node.key).toBe('b');
|
||||
expect(node).toEqual({
|
||||
_children: new Map(),
|
||||
_isEnd: false,
|
||||
_key: 'b'
|
||||
});
|
||||
});
|
||||
|
||||
it('should set children property correctly', () => {
|
||||
const node = new TrieNode('a');
|
||||
node.isEnd = false;
|
||||
const children = new Map<string, TrieNode>([['p', new TrieNode('p')]]);
|
||||
node.children = children;
|
||||
expect(node.children).toEqual(children);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Trie', () => {
|
||||
|
@ -865,29 +890,45 @@ describe('Trie class', () => {
|
|||
trie = new Trie(['apple', 'app', 'banana', 'band', 'bandana']);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should iterate over all words', () => {
|
||||
it('[Symbol.iterator] should iterate over all words', () => {
|
||||
const words = [...trie];
|
||||
expect(words).toEqual(['app', 'apple', 'banana', 'band', 'bandana']);
|
||||
});
|
||||
|
||||
test('forEach should execute a callback for each word', () => {
|
||||
it('forEach should execute a callback for each word', () => {
|
||||
const mockCallback = jest.fn();
|
||||
trie.forEach(mockCallback);
|
||||
expect(mockCallback).toHaveBeenCalledTimes(5);
|
||||
});
|
||||
|
||||
test('filter should return words that satisfy the predicate', () => {
|
||||
it('filter should return words that satisfy the predicate', () => {
|
||||
const filteredWords = trie.filter(word => word.startsWith('ba'));
|
||||
expect([...filteredWords]).toEqual(['banana', 'band', 'bandana']);
|
||||
});
|
||||
|
||||
test('map should apply a function to each word', () => {
|
||||
it('map should apply a function to each word', () => {
|
||||
const mappedWords = trie.map(word => word.length.toString());
|
||||
expect([...mappedWords]).toEqual(['3', '5', '6', '4', '7']);
|
||||
});
|
||||
|
||||
test('reduce should reduce the words to a single value', () => {
|
||||
it('reduce should reduce the words to a single value', () => {
|
||||
const concatenatedWords = trie.reduce((acc, word) => acc + word, '');
|
||||
expect(concatenatedWords).toEqual('appapplebananabandbandana');
|
||||
});
|
||||
|
||||
it('reduce should new Trie with toElementFn be correct', () => {
|
||||
const trieB = new Trie([{ name: 'apple' }, { name: 'app' }, { name: 'arm' }], { toElementFn: item => item.name });
|
||||
expect(trieB.isEmpty()).toBe(false);
|
||||
expect(trieB.size).toBe(3);
|
||||
expect(trieB.has('apple')).toBe(true);
|
||||
expect(trieB.has('app')).toBe(true);
|
||||
expect(trieB.has('arm')).toBe(true);
|
||||
expect(trieB.hasPrefix('ap')).toBe(true);
|
||||
trieB.clear();
|
||||
expect(trieB.size).toBe(0);
|
||||
expect(trieB.has('apple')).toBe(false);
|
||||
expect(trieB.has('app')).toBe(false);
|
||||
expect(trieB.has('arm')).toBe(false);
|
||||
expect(trieB.hasPrefix('ap')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue