mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
feat: Provide custom toElementFn in Heap configuration options to transform user raw data into a specified element type within a single loop.
This commit is contained in:
parent
8051850331
commit
6539e50598
|
@ -20,7 +20,7 @@ import { IterableElementBase } from '../base';
|
|||
* 7. Efficient Sorting Algorithms: For example, heap sort. Heap sort uses the properties of a heap to sort elements.
|
||||
* 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prime's minimum-spanning tree algorithm, which use heaps to improve performance.
|
||||
*/
|
||||
export class Heap<E = any> extends IterableElementBase<E> {
|
||||
export class Heap<E = any, R = any> extends IterableElementBase<E> {
|
||||
/**
|
||||
* The constructor initializes a heap data structure with optional elements and options.
|
||||
* @param elements - The `elements` parameter is an iterable object that contains the initial
|
||||
|
@ -34,17 +34,18 @@ export class Heap<E = any> extends IterableElementBase<E> {
|
|||
* The comparator function is used to determine the
|
||||
* order of elements in the heap.
|
||||
*/
|
||||
constructor(elements: Iterable<E> = [], options?: HeapOptions<E>) {
|
||||
constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {
|
||||
super();
|
||||
|
||||
if (options) {
|
||||
const { comparator } = options;
|
||||
const { comparator, toElementFn } = options;
|
||||
if (comparator) this._comparator = comparator;
|
||||
if (toElementFn) this._toElementFn = toElementFn;
|
||||
}
|
||||
|
||||
if (elements) {
|
||||
for (const el of elements) {
|
||||
this.add(el);
|
||||
if (this._toElementFn) this.add(this._toElementFn(el as R));
|
||||
else this.add(el as E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +60,12 @@ export class Heap<E = any> extends IterableElementBase<E> {
|
|||
return this._elements;
|
||||
}
|
||||
|
||||
protected _toElementFn?: (rawElement: R) => E;
|
||||
|
||||
get toElementFn() {
|
||||
return this._toElementFn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size (number of elements) of the heap.
|
||||
*/
|
||||
|
@ -80,7 +87,7 @@ export class Heap<E = any> extends IterableElementBase<E> {
|
|||
* @param elements
|
||||
* @param options
|
||||
*/
|
||||
static heapify<E>(elements: Iterable<E>, options: HeapOptions<E>): Heap<E> {
|
||||
static heapify<E = any, R = any>(elements: Iterable<E>, options: HeapOptions<E, R>): Heap<E> {
|
||||
return new Heap<E>(elements, options);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,12 +16,11 @@ import { Heap } from './heap';
|
|||
* 5. Managing Dynamic Data Sets: Heaps effectively manage dynamic data sets, especially when frequent access to the largest or smallest elements is required.
|
||||
* 6. Non-linear Search: While a heap allows rapid access to its largest or smallest element, it is less efficient for other operations, such as searching for a specific element, as it is not designed for these tasks.
|
||||
* 7. Efficient Sorting Algorithms: For example, heap sort. Heap sort uses the properties of a heap to sort elements.
|
||||
* 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prim's minimum spanning tree algorithm, which use heaps to improve performance.
|
||||
* 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prim's minimum-spanning tree algorithm, which use heaps to improve performance.
|
||||
*/
|
||||
export class MaxHeap<E = any> extends Heap<E> {
|
||||
constructor(
|
||||
elements: Iterable<E> = [],
|
||||
options: HeapOptions<E> = {
|
||||
export class MaxHeap<E = any, R = any> extends Heap<E> {
|
||||
constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {
|
||||
super(elements, {
|
||||
comparator: (a: E, b: E): number => {
|
||||
if (typeof a === 'object' || typeof b === 'object') {
|
||||
throw TypeError(
|
||||
|
@ -31,9 +30,8 @@ export class MaxHeap<E = any> extends Heap<E> {
|
|||
if (a < b) return 1;
|
||||
if (a > b) return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
) {
|
||||
super(elements, options);
|
||||
},
|
||||
...options
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ import { Heap } from './heap';
|
|||
* 7. Efficient Sorting Algorithms: For example, heap sort. Heap sort uses the properties of a heap to sort elements.
|
||||
* 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prim's minimum spanning tree algorithm, which use heaps to improve performance.
|
||||
*/
|
||||
export class MinHeap<E = any> extends Heap<E> {
|
||||
constructor(elements: Iterable<E> = [], options?: HeapOptions<E>) {
|
||||
export class MinHeap<E = any, R = any> extends Heap<E> {
|
||||
constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {
|
||||
super(elements, options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import type { PriorityQueueOptions } from '../../types';
|
||||
import { PriorityQueue } from './priority-queue';
|
||||
|
||||
export class MaxPriorityQueue<E = any> extends PriorityQueue<E> {
|
||||
export class MaxPriorityQueue<E = any, R = any> extends PriorityQueue<E> {
|
||||
/**
|
||||
* The constructor initializes a PriorityQueue with optional elements and options, including a
|
||||
* comparator function.
|
||||
|
@ -16,21 +16,22 @@ export class MaxPriorityQueue<E = any> extends PriorityQueue<E> {
|
|||
* elements to be added to the priority queue. It is optional and defaults to an empty array if not
|
||||
* provided.
|
||||
* @param options - The `options` parameter is an object that contains additional configuration
|
||||
* options for the priority queue. In this case, it has a property called `comparator` which is a
|
||||
* options for the priority queue. In this case, it has a property called `comparator,` which is a
|
||||
* function used to compare elements in the priority queue.
|
||||
*/
|
||||
constructor(
|
||||
elements: Iterable<E> = [],
|
||||
options: PriorityQueueOptions<E> = {
|
||||
comparator: (a: E, b: E) => {
|
||||
if (!(typeof a === 'number' && typeof b === 'number')) {
|
||||
throw new Error('The a, b params of compare function must be number');
|
||||
} else {
|
||||
return b - a;
|
||||
constructor(elements: Iterable<E> | Iterable<R> = [], options?: PriorityQueueOptions<E, R>) {
|
||||
super(elements, {
|
||||
comparator: (a: E, b: E): number => {
|
||||
if (typeof a === 'object' || typeof b === 'object') {
|
||||
throw TypeError(
|
||||
`When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
super(elements, options);
|
||||
if (a < b) return 1;
|
||||
if (a > b) return -1;
|
||||
return 0;
|
||||
},
|
||||
...options
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import type { PriorityQueueOptions } from '../../types';
|
||||
import { PriorityQueue } from './priority-queue';
|
||||
|
||||
export class MinPriorityQueue<E = any> extends PriorityQueue<E> {
|
||||
export class MinPriorityQueue<E = any, R = any> extends PriorityQueue<E> {
|
||||
/**
|
||||
* The constructor initializes a PriorityQueue with optional elements and options, including a
|
||||
* comparator function.
|
||||
|
@ -16,22 +16,11 @@ export class MinPriorityQueue<E = any> extends PriorityQueue<E> {
|
|||
* elements to be added to the priority queue. It is optional and defaults to an empty array if not
|
||||
* provided.
|
||||
* @param options - The `options` parameter is an object that contains additional configuration
|
||||
* options for the priority queue. In this case, it has a property called `comparator` which is a
|
||||
* options for the priority queue. In this case, it has a property called `comparator,` which is a
|
||||
* function used to compare elements in the priority queue. The `comparator` function takes two
|
||||
* parameters `a` and `b`,
|
||||
* parameters `a` and `b`
|
||||
*/
|
||||
constructor(
|
||||
elements: Iterable<E> = [],
|
||||
options: PriorityQueueOptions<E> = {
|
||||
comparator: (a: E, b: E) => {
|
||||
if (!(typeof a === 'number' && typeof b === 'number')) {
|
||||
throw new Error('The a, b params of compare function must be number');
|
||||
} else {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
constructor(elements: Iterable<E> | Iterable<R> = [], options?: PriorityQueueOptions<E, R>) {
|
||||
super(elements, options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,16 +16,16 @@ import { Heap } from '../heap';
|
|||
* 5. Huffman Coding: Used to select the smallest node combination when constructing a Huffman tree.
|
||||
* 6. Kth Largest Element in a Data Stream: Used to maintain a min-heap of size K for quickly finding the Kth largest element in stream data
|
||||
*/
|
||||
export class PriorityQueue<E = any> extends Heap<E> {
|
||||
export class PriorityQueue<E = any, R = any> extends Heap<E, R> {
|
||||
/**
|
||||
* The constructor initializes a priority queue with optional elements and options.
|
||||
* @param elements - The `elements` parameter is an iterable object that contains the initial
|
||||
* elements to be added to the priority queue. It is an optional parameter and if not provided, the
|
||||
* elements to be added to the priority queue. It is an optional parameter, and if not provided, the
|
||||
* priority queue will be initialized as empty.
|
||||
* @param [options] - The `options` parameter is an optional object that can be used to customize the
|
||||
* behavior of the priority queue. It can contain the following properties:
|
||||
*/
|
||||
constructor(elements: Iterable<E> = [], options?: PriorityQueueOptions<E>) {
|
||||
constructor(elements: Iterable<E> | Iterable<R> = [], options?: PriorityQueueOptions<E, R>) {
|
||||
super(elements, options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,6 @@ export type BinaryTreeNodeNested<K, V> = BinaryTreeNode<K, V, BinaryTreeNode<K,
|
|||
export type BinaryTreeNested<K, V, R, NODE extends BinaryTreeNode<K, V, NODE>> = BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type BinaryTreeOptions<K, V, R> = {
|
||||
iterationType?: IterationType
|
||||
iterationType?: IterationType;
|
||||
toEntryFn?: (rawElement: R) => BTNEntry<K, V>;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import { Comparator } from '../../common';
|
||||
|
||||
export type HeapOptions<T> = { comparator?: Comparator<T> };
|
||||
export type HeapOptions<E, R> = {
|
||||
comparator?: Comparator<E>;
|
||||
toElementFn?: (rawElement: R) => E;
|
||||
};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { HeapOptions } from '../heap';
|
||||
|
||||
export type PriorityQueueOptions<T> = HeapOptions<T> & {};
|
||||
export type PriorityQueueOptions<E, R> = HeapOptions<E, R> & {};
|
||||
|
|
|
@ -87,6 +87,48 @@ describe('Heap Operation Test', () => {
|
|||
maxI++;
|
||||
}
|
||||
});
|
||||
|
||||
it('should object heap', () => {
|
||||
const heap = new Heap<{ rawItem: { id: number } }>(
|
||||
[
|
||||
{ rawItem: { id: 4 } },
|
||||
{ rawItem: { id: 8 } },
|
||||
{ rawItem: { id: 6 } },
|
||||
{ rawItem: { id: 7 } },
|
||||
{ rawItem: { id: 1 } },
|
||||
{ rawItem: { id: 3 } },
|
||||
{ rawItem: { id: 5 } }
|
||||
],
|
||||
{ comparator: (a, b) => a.rawItem.id - b.rawItem.id }
|
||||
);
|
||||
|
||||
expect([...heap.sort()]).toEqual([
|
||||
{ rawItem: { id: 1 } },
|
||||
{ rawItem: { id: 3 } },
|
||||
{ rawItem: { id: 4 } },
|
||||
{ rawItem: { id: 5 } },
|
||||
{ rawItem: { id: 6 } },
|
||||
{ rawItem: { id: 7 } },
|
||||
{ rawItem: { id: 8 } }
|
||||
]);
|
||||
});
|
||||
|
||||
it('should toElementFn', () => {
|
||||
const heap = new Heap<number, { rawItem: { id: number } }>(
|
||||
[
|
||||
{ rawItem: { id: 4 } },
|
||||
{ rawItem: { id: 8 } },
|
||||
{ rawItem: { id: 6 } },
|
||||
{ rawItem: { id: 7 } },
|
||||
{ rawItem: { id: 1 } },
|
||||
{ rawItem: { id: 3 } },
|
||||
{ rawItem: { id: 5 } }
|
||||
],
|
||||
{ toElementFn: rawElement => rawElement.rawItem.id }
|
||||
);
|
||||
|
||||
expect([...heap.sort()]).toEqual([1, 3, 4, 5, 6, 7, 8]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('FibonacciHeap', () => {
|
||||
|
|
|
@ -71,4 +71,46 @@ describe('MaxPriorityQueue Operation Test', () => {
|
|||
expect(maxPQ.poll()?.keyA).toBe(3);
|
||||
expect(maxPQ.poll()?.keyA).toBe(1);
|
||||
});
|
||||
|
||||
it('should object priority queue', () => {
|
||||
const maxPQ = new MaxPriorityQueue<{ rawItem: { id: number } }>(
|
||||
[
|
||||
{ rawItem: { id: 4 } },
|
||||
{ rawItem: { id: 8 } },
|
||||
{ rawItem: { id: 6 } },
|
||||
{ rawItem: { id: 7 } },
|
||||
{ rawItem: { id: 1 } },
|
||||
{ rawItem: { id: 3 } },
|
||||
{ rawItem: { id: 5 } }
|
||||
],
|
||||
{ comparator: (a, b) => b.rawItem.id - a.rawItem.id }
|
||||
);
|
||||
|
||||
expect([...maxPQ.sort()]).toEqual([
|
||||
{ rawItem: { id: 8 } },
|
||||
{ rawItem: { id: 7 } },
|
||||
{ rawItem: { id: 6 } },
|
||||
{ rawItem: { id: 5 } },
|
||||
{ rawItem: { id: 4 } },
|
||||
{ rawItem: { id: 3 } },
|
||||
{ rawItem: { id: 1 } }
|
||||
]);
|
||||
});
|
||||
|
||||
it('should toElementFn', () => {
|
||||
const maxPQ = new MaxPriorityQueue<number, { rawItem: { id: number } }>(
|
||||
[
|
||||
{ rawItem: { id: 4 } },
|
||||
{ rawItem: { id: 8 } },
|
||||
{ rawItem: { id: 6 } },
|
||||
{ rawItem: { id: 7 } },
|
||||
{ rawItem: { id: 1 } },
|
||||
{ rawItem: { id: 3 } },
|
||||
{ rawItem: { id: 5 } }
|
||||
],
|
||||
{ toElementFn: rawElement => rawElement.rawItem.id }
|
||||
);
|
||||
|
||||
expect([...maxPQ.sort()]).toEqual([8, 7, 6, 5, 4, 3, 1]);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue