mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
[BinaryTree, Heap] In abstract classes, only retain abstract methods. Replace the generic 'T' with 'E' in Heap and PriorityQueue
This commit is contained in:
parent
b4448bb0d3
commit
727cc87ca5
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "data-structure-typed",
|
||||
"version": "1.40.0-rc",
|
||||
"version": "1.36.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "data-structure-typed",
|
||||
"version": "1.40.0-rc",
|
||||
"version": "1.36.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/benchmark": "^2.1.3",
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,9 +9,9 @@ import {BST, BSTNode} from './bst';
|
|||
import type {AVLTreeNodeNested, AVLTreeOptions, BinaryTreeDeletedResult, BinaryTreeNodeKey} from '../../types';
|
||||
import {IAVLTree, IAVLTreeNode} from '../../interfaces';
|
||||
|
||||
export class AVLTreeNode<V = any, NEIGHBOR extends AVLTreeNode<V, NEIGHBOR> = AVLTreeNodeNested<V>>
|
||||
extends BSTNode<V, NEIGHBOR>
|
||||
implements IAVLTreeNode<V, NEIGHBOR>
|
||||
export class AVLTreeNode<V = any, FAMILY extends AVLTreeNode<V, FAMILY> = AVLTreeNodeNested<V>>
|
||||
extends BSTNode<V, FAMILY>
|
||||
implements IAVLTreeNode<V, FAMILY>
|
||||
{
|
||||
height: number;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,9 +16,9 @@ import {CP, LoopType} from '../../types';
|
|||
import {BinaryTree, BinaryTreeNode} from './binary-tree';
|
||||
import {IBST, IBSTNode} from '../../interfaces';
|
||||
|
||||
export class BSTNode<V = any, NEIGHBOR extends BSTNode<V, NEIGHBOR> = BSTNodeNested<V>>
|
||||
extends BinaryTreeNode<V, NEIGHBOR>
|
||||
implements IBSTNode<V, NEIGHBOR>
|
||||
export class BSTNode<V = any, FAMILY extends BSTNode<V, FAMILY> = BSTNodeNested<V>>
|
||||
extends BinaryTreeNode<V, FAMILY>
|
||||
implements IBSTNode<V, FAMILY>
|
||||
{
|
||||
constructor(key: BinaryTreeNodeKey, val?: V) {
|
||||
super(key, val);
|
||||
|
|
|
@ -2,9 +2,9 @@ import {BinaryTreeNodeKey, RBColor, RBTreeNodeNested, RBTreeOptions} from '../..
|
|||
import {IRBTree, IRBTreeNode} from '../../interfaces';
|
||||
import {BST, BSTNode} from './bst';
|
||||
|
||||
export class RBTreeNode<V = any, NEIGHBOR extends RBTreeNode<V, NEIGHBOR> = RBTreeNodeNested<V>>
|
||||
extends BSTNode<V, NEIGHBOR>
|
||||
implements IRBTreeNode<V, NEIGHBOR>
|
||||
export class RBTreeNode<V = any, FAMILY extends RBTreeNode<V, FAMILY> = RBTreeNodeNested<V>>
|
||||
extends BSTNode<V, FAMILY>
|
||||
implements IRBTreeNode<V, FAMILY>
|
||||
{
|
||||
private _color: RBColor;
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ import {BinaryTreeDeletedResult, CP, DFSOrderPattern, FamilyPosition, LoopType}
|
|||
import {ITreeMultiset, ITreeMultisetNode} from '../../interfaces';
|
||||
import {AVLTree, AVLTreeNode} from './avl-tree';
|
||||
|
||||
export class TreeMultisetNode<V = any, NEIGHBOR extends TreeMultisetNode<V, NEIGHBOR> = TreeMultisetNodeNested<V>>
|
||||
extends AVLTreeNode<V, NEIGHBOR>
|
||||
implements ITreeMultisetNode<V, NEIGHBOR>
|
||||
export class TreeMultisetNode<V = any, FAMILY extends TreeMultisetNode<V, FAMILY> = TreeMultisetNodeNested<V>>
|
||||
extends AVLTreeNode<V, FAMILY>
|
||||
implements ITreeMultisetNode<V, FAMILY>
|
||||
{
|
||||
/**
|
||||
* The constructor function initializes a BinaryTreeNode object with a key, value, and count.
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
import type {CompareFunction} from '../../types';
|
||||
|
||||
export class Heap<T> {
|
||||
private nodes: T[] = [];
|
||||
private readonly comparator: CompareFunction<T>;
|
||||
export class Heap<E> {
|
||||
protected nodes: E[] = [];
|
||||
private readonly comparator: CompareFunction<E>;
|
||||
|
||||
constructor(comparator: CompareFunction<T>) {
|
||||
constructor(comparator: CompareFunction<E>) {
|
||||
this.comparator = comparator;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ export class Heap<T> {
|
|||
* Insert an element into the heap and maintain the heap properties.
|
||||
* @param value - The element to be inserted.
|
||||
*/
|
||||
add(value: T): Heap<T> {
|
||||
add(value: E): Heap<E> {
|
||||
this.nodes.push(value);
|
||||
this.bubbleUp(this.nodes.length - 1);
|
||||
return this;
|
||||
|
@ -29,16 +29,16 @@ export class Heap<T> {
|
|||
* Remove and return the top element (smallest or largest element) from the heap.
|
||||
* @returns The top element or null if the heap is empty.
|
||||
*/
|
||||
poll(): T | null {
|
||||
poll(): E | null {
|
||||
if (this.nodes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (this.nodes.length === 1) {
|
||||
return this.nodes.pop() as T;
|
||||
return this.nodes.pop() as E;
|
||||
}
|
||||
|
||||
const topValue = this.nodes[0];
|
||||
this.nodes[0] = this.nodes.pop() as T;
|
||||
this.nodes[0] = this.nodes.pop() as E;
|
||||
this.sinkDown(0);
|
||||
return topValue;
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ export class Heap<T> {
|
|||
* Peek at the top element of the heap without removing it.
|
||||
* @returns The top element or null if the heap is empty.
|
||||
*/
|
||||
peek(): T | null {
|
||||
peek(): E | null {
|
||||
if (this.nodes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ export class Heap<T> {
|
|||
* Get the last element in the heap, which is not necessarily a leaf node.
|
||||
* @returns The last element or null if the heap is empty.
|
||||
*/
|
||||
leaf(): T | null {
|
||||
get leaf(): E | null {
|
||||
return this.nodes[this.size - 1] ?? null;
|
||||
}
|
||||
|
||||
|
@ -128,11 +128,18 @@ export class Heap<T> {
|
|||
return this.size === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the nodes of the heap. Make the nodes empty.
|
||||
*/
|
||||
clear() {
|
||||
this.nodes = [];
|
||||
}
|
||||
|
||||
refill(nodes: T[]) {
|
||||
/**
|
||||
* Clear and add nodes of the heap
|
||||
* @param nodes
|
||||
*/
|
||||
refill(nodes: E[]) {
|
||||
this.nodes = nodes;
|
||||
this.fix();
|
||||
}
|
||||
|
@ -142,41 +149,17 @@ export class Heap<T> {
|
|||
* @param value - the element to check.
|
||||
* @returns Returns true if the specified element is contained; otherwise, returns false.
|
||||
*/
|
||||
has(value: T): boolean {
|
||||
has(value: E): boolean {
|
||||
return this.nodes.includes(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a comparison function to find the index of an element in the heap.
|
||||
* @param value - the element to find.
|
||||
* @param index - the index currently being searched.
|
||||
* @returns The index of the element, or -1 if not found.
|
||||
*/
|
||||
private findIndex(value: T, index: number): number {
|
||||
if (index >= this.size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const compareResult = this.comparator(value, this.nodes[index]);
|
||||
|
||||
if (compareResult === 0) {
|
||||
return index; // Element found
|
||||
} else if (compareResult < 0) {
|
||||
// The element should be in the left subtree
|
||||
return this.findIndex(value, 2 * index + 1);
|
||||
} else {
|
||||
// The element should be in the right subtree
|
||||
return this.findIndex(value, 2 * index + 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Depth-first search (DFS) method, different traversal orders can be selected。
|
||||
* @param order - Traversal order parameter: 'in' (in-order), 'pre' (pre-order) or 'post' (post-order).
|
||||
* @returns An array containing elements traversed in the specified order.
|
||||
*/
|
||||
dfs(order: 'in' | 'pre' | 'post'): T[] {
|
||||
const result: T[] = [];
|
||||
dfs(order: 'in' | 'pre' | 'post'): E[] {
|
||||
const result: E[] = [];
|
||||
|
||||
// Auxiliary recursive function, traverses the binary heap according to the traversal order
|
||||
const dfsHelper = (index: number) => {
|
||||
|
@ -206,11 +189,11 @@ export class Heap<T> {
|
|||
* Convert the heap to an array.
|
||||
* @returns An array containing the elements of the heap.
|
||||
*/
|
||||
toArray(): T[] {
|
||||
toArray(): E[] {
|
||||
return [...this.nodes];
|
||||
}
|
||||
|
||||
getNodes(): T[] {
|
||||
getNodes(): E[] {
|
||||
return this.nodes;
|
||||
}
|
||||
|
||||
|
@ -218,8 +201,8 @@ export class Heap<T> {
|
|||
* Clone the heap, creating a new heap with the same elements.
|
||||
* @returns A new Heap instance containing the same elements.
|
||||
*/
|
||||
clone(): Heap<T> {
|
||||
const clonedHeap = new Heap<T>(this.comparator);
|
||||
clone(): Heap<E> {
|
||||
const clonedHeap = new Heap<E>(this.comparator);
|
||||
clonedHeap.nodes = [...this.nodes];
|
||||
return clonedHeap;
|
||||
}
|
||||
|
@ -228,8 +211,8 @@ export class Heap<T> {
|
|||
* Sort the elements in the heap and return them as an array.
|
||||
* @returns An array containing the elements sorted in ascending order.
|
||||
*/
|
||||
sort(): T[] {
|
||||
const visitedNode: T[] = [];
|
||||
sort(): E[] {
|
||||
const visitedNode: E[] = [];
|
||||
const cloned = this.clone();
|
||||
while (cloned.size !== 0) {
|
||||
const top = cloned.poll();
|
||||
|
@ -244,8 +227,8 @@ export class Heap<T> {
|
|||
* @param comparator - Comparison function.
|
||||
* @returns A new Heap instance.
|
||||
*/
|
||||
static heapify<T>(nodes: T[], comparator: CompareFunction<T>): Heap<T> {
|
||||
const binaryHeap = new Heap<T>(comparator);
|
||||
static heapify<E>(nodes: E[], comparator: CompareFunction<E>): Heap<E> {
|
||||
const binaryHeap = new Heap<E>(comparator);
|
||||
binaryHeap.nodes = [...nodes];
|
||||
binaryHeap.fix(); // Fix heap properties
|
||||
return binaryHeap;
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
import {Heap} from './heap';
|
||||
import type {CompareFunction} from '../../types';
|
||||
|
||||
export class MaxHeap<T = any> extends Heap<T> {
|
||||
export class MaxHeap<E = any> extends Heap<E> {
|
||||
constructor(
|
||||
comparator: CompareFunction<T> = (a: T, b: T) => {
|
||||
comparator: CompareFunction<E> = (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 {
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
import {Heap} from './heap';
|
||||
import type {CompareFunction} from '../../types';
|
||||
|
||||
export class MinHeap<T = any> extends Heap<T> {
|
||||
export class MinHeap<E = any> extends Heap<E> {
|
||||
constructor(
|
||||
comparator: CompareFunction<T> = (a: T, b: T) => {
|
||||
comparator: CompareFunction<E> = (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 {
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
import {PriorityQueue} from './priority-queue';
|
||||
import type {CompareFunction} from '../../types';
|
||||
|
||||
export class MaxPriorityQueue<T = any> extends PriorityQueue<T> {
|
||||
export class MaxPriorityQueue<E = any> extends PriorityQueue<E> {
|
||||
constructor(
|
||||
compare: CompareFunction<T> = (a: T, b: T) => {
|
||||
compare: CompareFunction<E> = (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 {
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
import {PriorityQueue} from './priority-queue';
|
||||
import type {CompareFunction} from '../../types';
|
||||
|
||||
export class MinPriorityQueue<T = any> extends PriorityQueue<T> {
|
||||
export class MinPriorityQueue<E = any> extends PriorityQueue<E> {
|
||||
constructor(
|
||||
compare: CompareFunction<T> = (a: T, b: T) => {
|
||||
compare: CompareFunction<E> = (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 {
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
import {Heap} from '../heap';
|
||||
import {CompareFunction} from '../../types';
|
||||
|
||||
export class PriorityQueue<T> extends Heap<T> {
|
||||
constructor(comparator: CompareFunction<T>) {
|
||||
export class PriorityQueue<E> extends Heap<E> {
|
||||
constructor(comparator: CompareFunction<E>) {
|
||||
super(comparator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,5 +45,5 @@ export type AbstractBinaryTreeNodeProperties<N extends AbstractBinaryTreeNode<N[
|
|||
export type AbstractBinaryTreeNodeNested<T> = AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
|
||||
|
||||
export type AbstractBinaryTreeOptions = {
|
||||
loopType?: LoopType
|
||||
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {BinaryTreeNode} from '../../data-structures/binary-tree';
|
||||
import {AbstractBinaryTreeOptions} from './abstract-binary-tree';
|
||||
import {AbstractBinaryTreeOptions, LoopType} from './abstract-binary-tree';
|
||||
|
||||
export type BinaryTreeNodeNested<T> = BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
export type BinaryTreeOptions = AbstractBinaryTreeOptions & {}
|
||||
export type BinaryTreeOptions = AbstractBinaryTreeOptions & { loopType?: LoopType }
|
||||
|
|
|
@ -89,7 +89,8 @@ describe('MaxPriorityQueue Performance Test', () => {
|
|||
prev = polled;
|
||||
}
|
||||
}
|
||||
expect(performance.now() - startTime).toBeLessThan(bigO.LINEAR * 50);
|
||||
const cost = performance.now() - startTime;
|
||||
expect(cost).toBeLessThan(bigO.LINEAR * 20);
|
||||
expect(prev).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ describe('MinPriorityQueue Operation Test', () => {
|
|||
priorityQueue.add(3);
|
||||
priorityQueue.add(7);
|
||||
|
||||
expect(priorityQueue.leaf()).toBe(7);
|
||||
expect(priorityQueue.leaf).toBe(7);
|
||||
});
|
||||
|
||||
it('should check if the queue is empty', () => {
|
||||
|
|
Loading…
Reference in a new issue