mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2025-01-18 11:14:05 +00:00
feat: Added multiple methods to all linear data structures (Queue, Deque, DoublyLinkedList, SinglyLinkedList), including join, concat, sort, slice, lastIndexOf, findIndex, splice, reduceRight, and fill. Abstracted LinearBase and LinearLinkedBase classes to implement high-performance member methods tailored to different data types.
This commit is contained in:
parent
731ef56e10
commit
4a522db1e3
|
@ -1,6 +1,6 @@
|
|||
import { ElementCallback, IterableElementBaseOptions, ReduceElementCallback } from '../../types';
|
||||
|
||||
export abstract class IterableElementBase<E, R, C> {
|
||||
export abstract class IterableElementBase<E, R> {
|
||||
/**
|
||||
* The protected constructor initializes the options for the IterableElementBase class, including the
|
||||
* toElementFn function.
|
||||
|
@ -14,17 +14,8 @@ export abstract class IterableElementBase<E, R, C> {
|
|||
}
|
||||
}
|
||||
|
||||
// abstract get size(): number;
|
||||
|
||||
protected _toElementFn?: (rawElement: R) => E;
|
||||
|
||||
/**
|
||||
* The function returns the _toElementFn property, which is a function that converts a raw element to
|
||||
* a specific type.
|
||||
* @returns The function `get toElementFn()` is returning either a function that takes a raw element
|
||||
* `rawElement` of type `R` and returns an element `E`, or `undefined` if no function is assigned to
|
||||
* `_toElementFn`.
|
||||
*/
|
||||
get toElementFn(): ((rawElement: R) => E) | undefined {
|
||||
return this._toElementFn;
|
||||
}
|
||||
|
@ -68,7 +59,7 @@ export abstract class IterableElementBase<E, R, C> {
|
|||
* @returns The `every` method is returning a boolean value. It returns `true` if every element in
|
||||
* the array satisfies the provided predicate function, and `false` otherwise.
|
||||
*/
|
||||
every(predicate: ElementCallback<E, R, boolean, C>, thisArg?: any): boolean {
|
||||
every(predicate: ElementCallback<E, R, boolean>, thisArg?: any): boolean {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
if (!predicate.call(thisArg, item, index++, this)) {
|
||||
|
@ -92,7 +83,7 @@ export abstract class IterableElementBase<E, R, C> {
|
|||
* @returns a boolean value. It returns true if the predicate function returns true for any element
|
||||
* in the collection, and false otherwise.
|
||||
*/
|
||||
some(predicate: ElementCallback<E, R, boolean, C>, thisArg?: any): boolean {
|
||||
some(predicate: ElementCallback<E, R, boolean>, thisArg?: any): boolean {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
if (predicate.call(thisArg, item, index++, this)) {
|
||||
|
@ -115,20 +106,23 @@ export abstract class IterableElementBase<E, R, C> {
|
|||
* to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
|
||||
* be passed as the `this` value to the `callbackfn` function. If `thisArg
|
||||
*/
|
||||
forEach(callbackfn: ElementCallback<E, R, void, C>, thisArg?: any): void {
|
||||
forEach(callbackfn: ElementCallback<E, R, void>, thisArg?: any): void {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
callbackfn.call(thisArg, item, index++, this);
|
||||
}
|
||||
}
|
||||
|
||||
find<S extends E>(predicate: ElementCallback<E, R, S>, thisArg?: any): S | undefined;
|
||||
find(predicate: ElementCallback<E, R, unknown>, thisArg?: any): E | undefined;
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `find` function iterates over the elements of an array-like object and returns the first
|
||||
* element that satisfies the provided callback function.
|
||||
* @param callbackfn - The callbackfn parameter is a function that will be called for each element in
|
||||
* @param predicate - The predicate parameter is a function that will be called for each element in
|
||||
* the array. It takes three arguments: the current element being processed, the index of the current
|
||||
* element, and the array itself. The function should return a boolean value indicating whether the
|
||||
* current element matches the desired condition.
|
||||
|
@ -138,10 +132,10 @@ export abstract class IterableElementBase<E, R, C> {
|
|||
* @returns The `find` method returns the first element in the array that satisfies the provided
|
||||
* callback function. If no element satisfies the callback function, `undefined` is returned.
|
||||
*/
|
||||
find(callbackfn: ElementCallback<E, R, boolean, C>, thisArg?: any): E | undefined {
|
||||
find(predicate: ElementCallback<E, R, boolean>, thisArg?: any): E | undefined {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
if (callbackfn.call(thisArg, item, index++, this)) return item;
|
||||
if (predicate.call(thisArg, item, index++, this)) return item;
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -164,6 +158,10 @@ export abstract class IterableElementBase<E, R, C> {
|
|||
return false;
|
||||
}
|
||||
|
||||
reduce(callbackfn: ReduceElementCallback<E, R>): E;
|
||||
reduce(callbackfn: ReduceElementCallback<E, R>, initialValue: E): E;
|
||||
reduce<U>(callbackfn: ReduceElementCallback<E, R, U>, initialValue: U): U;
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -177,15 +175,26 @@ export abstract class IterableElementBase<E, R, C> {
|
|||
* @returns The `reduce` method is returning the final value of the accumulator after iterating over
|
||||
* all the elements in the array and applying the callback function to each element.
|
||||
*/
|
||||
reduce<U>(callbackfn: ReduceElementCallback<E, R, U, C>, initialValue: U): U {
|
||||
let accumulator = initialValue;
|
||||
reduce<U>(callbackfn: ReduceElementCallback<E, R, U>, initialValue?: U): U {
|
||||
let accumulator = initialValue ?? (0 as U);
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
accumulator = callbackfn(accumulator, item as E, index++, this);
|
||||
accumulator = callbackfn(accumulator, item, index++, this);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `toArray` function converts a linked list into an array.
|
||||
* @returns The `toArray()` method is returning an array of type `E[]`.
|
||||
*/
|
||||
toArray(): E[] {
|
||||
return [...this];
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
|
@ -210,7 +219,7 @@ export abstract class IterableElementBase<E, R, C> {
|
|||
|
||||
abstract clear(): void;
|
||||
|
||||
abstract clone(): C;
|
||||
abstract clone(): IterableElementBase<E, R>;
|
||||
|
||||
abstract map(...args: any[]): any;
|
||||
|
||||
|
|
571
src/data-structures/base/linear-base.ts
Normal file
571
src/data-structures/base/linear-base.ts
Normal file
|
@ -0,0 +1,571 @@
|
|||
import { ElementCallback, LinearBaseOptions, ReduceLinearCallback } from '../../types';
|
||||
import { IterableElementBase } from './iterable-element-base';
|
||||
|
||||
export abstract class LinearBase<E, R = any, NODE = any> extends IterableElementBase<E, R> {
|
||||
protected constructor(options?: LinearBaseOptions<E, R>) {
|
||||
super(options);
|
||||
if (options) {
|
||||
const { maxLen } = options;
|
||||
if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;
|
||||
}
|
||||
}
|
||||
|
||||
abstract get length(): number;
|
||||
|
||||
protected _maxLen: number = -1;
|
||||
|
||||
get maxLen() {
|
||||
return this._maxLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function indexOf searches for a specified element starting from a given index in an array-like
|
||||
* object and returns the index of the first occurrence, or -1 if not found.
|
||||
* @param {E} searchElement - The `searchElement` parameter in the `indexOf` function represents the
|
||||
* element that you want to find within the array. The function will search for this element starting
|
||||
* from the `fromIndex` (if provided) up to the end of the array. If the `searchElement` is found
|
||||
* within the
|
||||
* @param {number} [fromIndex=0] - The `fromIndex` parameter in the `indexOf` function represents the
|
||||
* index at which to start searching for the `searchElement` within the array. If provided, the
|
||||
* search will begin at this index and continue to the end of the array. If `fromIndex` is not
|
||||
* specified, the default
|
||||
* @returns The `indexOf` method is returning the index of the `searchElement` if it is found in the
|
||||
* array starting from the `fromIndex`. If the `searchElement` is not found, it returns -1.
|
||||
*/
|
||||
indexOf(searchElement: E, fromIndex: number = 0): number {
|
||||
// Boundary checks and adjustments
|
||||
if (this.length === 0) return -1;
|
||||
if (fromIndex < 0) fromIndex = this.length + fromIndex;
|
||||
if (fromIndex < 0) fromIndex = 0;
|
||||
|
||||
// Iterating from the specified index to the end
|
||||
for (let i = fromIndex; i < this.length; i++) {
|
||||
const element = this.at(i);
|
||||
if (element === searchElement) return i;
|
||||
}
|
||||
|
||||
return -1; // Not found
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function `lastIndexOf` in TypeScript returns the index of the last occurrence of a specified
|
||||
* element in an array.
|
||||
* @param {E} searchElement - The `searchElement` parameter is the element that you want to find the
|
||||
* last index of within the array. The `lastIndexOf` method will search the array starting from the
|
||||
* `fromIndex` (or the end of the array if not specified) and return the index of the last occurrence
|
||||
* of the
|
||||
* @param {number} fromIndex - The `fromIndex` parameter in the `lastIndexOf` method specifies the
|
||||
* index at which to start searching for the `searchElement` in the array. By default, it starts
|
||||
* searching from the last element of the array (`this.length - 1`). If a specific `fromIndex` is
|
||||
* provided
|
||||
* @returns The last index of the `searchElement` in the array is being returned. If the
|
||||
* `searchElement` is not found in the array, -1 is returned.
|
||||
*/
|
||||
lastIndexOf(searchElement: E, fromIndex: number = this.length - 1): number {
|
||||
if (this.length === 0) return -1;
|
||||
if (fromIndex >= this.length) fromIndex = this.length - 1;
|
||||
if (fromIndex < 0) fromIndex = this.length + fromIndex;
|
||||
|
||||
for (let i = fromIndex; i >= 0; i--) {
|
||||
const element = this.at(i);
|
||||
if (element === searchElement) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `findIndex` function iterates over an array and returns the index of the first element that
|
||||
* satisfies the provided predicate function.
|
||||
* @param predicate - The `predicate` parameter in the `findIndex` function is a callback function
|
||||
* that takes three arguments: `item`, `index`, and the array `this`. It should return a boolean
|
||||
* value indicating whether the current element satisfies the condition being checked for.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter in the `findIndex` function is an optional
|
||||
* parameter that specifies the value to use as `this` when executing the `predicate` function. If
|
||||
* provided, the `predicate` function will be called with `thisArg` as its `this` value. If `
|
||||
* @returns The `findIndex` method is returning the index of the first element in the array that
|
||||
* satisfies the provided predicate function. If no such element is found, it returns -1.
|
||||
*/
|
||||
findIndex(predicate: ElementCallback<E, R, boolean>, thisArg?: any): number {
|
||||
for (let i = 0; i < this.length; i++) {
|
||||
const item = this.at(i);
|
||||
if (item !== undefined && predicate.call(thisArg, item, i, this)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
concat(...items: LinearBase<E, R>[]): this;
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n + m)
|
||||
* Space Complexity: O(n + m)
|
||||
*
|
||||
* The `concat` function in TypeScript concatenates multiple items into a new list, handling both
|
||||
* individual elements and instances of `LinearBase`.
|
||||
* @param {(E | LinearBase<E, R>)[]} items - The `concat` method takes in an array of items, where
|
||||
* each item can be either of type `E` or an instance of `LinearBase<E, R>`.
|
||||
* @returns The `concat` method is returning a new instance of the class that it belongs to, with the
|
||||
* items passed as arguments concatenated to it.
|
||||
*/
|
||||
concat(...items: (E | LinearBase<E, R>)[]): this {
|
||||
const newList = this.clone();
|
||||
|
||||
for (const item of items) {
|
||||
if (item instanceof LinearBase) {
|
||||
newList.pushMany(item);
|
||||
} else {
|
||||
newList.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return newList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n log n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `sort` function in TypeScript sorts the elements of a collection using a specified comparison
|
||||
* function.
|
||||
* @param [compareFn] - The `compareFn` parameter is a function that defines the sort order. It takes
|
||||
* two elements `a` and `b` as input and returns a number indicating their relative order. If the
|
||||
* returned value is negative, `a` comes before `b`. If the returned value is positive, `
|
||||
* @returns The `sort` method is returning the instance of the object on which it is called (this),
|
||||
* after sorting the elements based on the provided comparison function (compareFn).
|
||||
*/
|
||||
sort(compareFn?: (a: E, b: E) => number): this {
|
||||
const arr = this.toArray();
|
||||
arr.sort(compareFn);
|
||||
this.clear();
|
||||
for (const item of arr) this.push(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n + m)
|
||||
* Space Complexity: O(m)
|
||||
*
|
||||
* The `splice` function in TypeScript removes elements from an array and optionally inserts new
|
||||
* elements at the specified index.
|
||||
* @param {number} start - The `start` parameter in the `splice` method indicates the index at which
|
||||
* to start modifying the array. If `start` is a negative number, it will count from the end of the
|
||||
* array.
|
||||
* @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the
|
||||
* number of elements to remove from the array starting at the specified `start` index. If
|
||||
* `deleteCount` is not provided or is 0, no elements are removed, and only new elements are inserted
|
||||
* at the `start`
|
||||
* @param {E[]} items - The `items` parameter in the `splice` method represents the elements that
|
||||
* will be inserted into the array at the specified `start` index. These elements can be of any type
|
||||
* and you can pass multiple elements separated by commas. The `splice` method will insert these
|
||||
* items into the array at the
|
||||
* @returns The `splice` method returns a list of elements that were removed from the original list
|
||||
* during the operation.
|
||||
*/
|
||||
splice(start: number, deleteCount: number = 0, ...items: E[]): this {
|
||||
start = start < 0 ? this.length + start : start;
|
||||
if (start < 0) start = 0;
|
||||
if (start > this.length) start = this.length;
|
||||
|
||||
const removedList = this._createInstance({ toElementFn: this._toElementFn });
|
||||
|
||||
// Move to starting position
|
||||
let currentNode = this.at(start);
|
||||
let currentIndex = start;
|
||||
|
||||
// Delete elements
|
||||
for (let i = 0; i < deleteCount && currentNode !== undefined; i++) {
|
||||
removedList.push(currentNode);
|
||||
this.delete(currentNode);
|
||||
currentNode = this.at(currentIndex); // Update node reference
|
||||
}
|
||||
|
||||
// Insert new element
|
||||
for (const item of items) {
|
||||
this.addAt(currentIndex, item);
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
return removedList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `join` function in TypeScript returns a string by joining the elements of an array with a
|
||||
* specified separator.
|
||||
* @param {string} [separator=,] - The `separator` parameter is a string that specifies the character
|
||||
* or characters that will be used to separate each element when joining them into a single string.
|
||||
* By default, the separator is set to a comma (`,`), but you can provide a different separator if
|
||||
* needed.
|
||||
* @returns The `join` method is being returned, which takes an optional `separator` parameter
|
||||
* (defaulting to a comma) and returns a string created by joining all elements of the array after
|
||||
* converting it to an array.
|
||||
*/
|
||||
join(separator: string = ','): string {
|
||||
return this.toArray().join(separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The function `toReversedArray` takes an array and returns a new array with its elements in reverse
|
||||
* order.
|
||||
* @returns The `toReversedArray()` function returns an array of elements of type `E` in reverse
|
||||
* order.
|
||||
*/
|
||||
toReversedArray(): E[] {
|
||||
const array: E[] = [];
|
||||
for (let i = this.length - 1; i >= 0; i--) {
|
||||
array.push(this.at(i)!);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
reduceRight(callbackfn: ReduceLinearCallback<E>): E;
|
||||
|
||||
reduceRight(callbackfn: ReduceLinearCallback<E>, initialValue: E): E;
|
||||
|
||||
reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue: U): U;
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `reduceRight` function in TypeScript iterates over an array from right to left and applies a
|
||||
* callback function to each element, accumulating a single result.
|
||||
* @param callbackfn - The `callbackfn` parameter in the `reduceRight` method is a function that will
|
||||
* be called on each element in the array from right to left. It takes four arguments:
|
||||
* @param {U} [initialValue] - The `initialValue` parameter in the `reduceRight` method is an
|
||||
* optional parameter that specifies the initial value of the accumulator. If provided, the
|
||||
* `accumulator` will start with this initial value before iterating over the elements of the array.
|
||||
* If `initialValue` is not provided, the accumulator will
|
||||
* @returns The `reduceRight` method is returning the final accumulated value after applying the
|
||||
* callback function to each element in the array from right to left.
|
||||
*/
|
||||
reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue?: U): U {
|
||||
let accumulator = initialValue ?? (0 as U);
|
||||
for (let i = this.length - 1; i >= 0; i--) {
|
||||
accumulator = callbackfn(accumulator, this.at(i)!, i, this);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(m)
|
||||
* Space Complexity: O(m)
|
||||
*
|
||||
* The `slice` function in TypeScript creates a new instance by extracting a portion of elements from
|
||||
* the original instance based on the specified start and end indices.
|
||||
* @param {number} [start=0] - The `start` parameter in the `slice` method represents the index at
|
||||
* which to begin extracting elements from an array-like object. If no `start` parameter is provided,
|
||||
* the default value is 0, meaning the extraction will start from the beginning of the array.
|
||||
* @param {number} end - The `end` parameter in the `slice` method represents the index at which to
|
||||
* end the slicing. By default, if no `end` parameter is provided, it will slice until the end of the
|
||||
* array (i.e., `this.length`).
|
||||
* @returns The `slice` method is returning a new instance of the object with elements sliced from
|
||||
* the specified start index (default is 0) to the specified end index (default is the length of the
|
||||
* object).
|
||||
*/
|
||||
slice(start: number = 0, end: number = this.length): this {
|
||||
start = start < 0 ? this.length + start : start;
|
||||
end = end < 0 ? this.length + end : end;
|
||||
|
||||
const newList = this._createInstance();
|
||||
for (let i = start; i < end; i++) {
|
||||
newList.push(this.at(i)!);
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `fill` function in TypeScript fills a specified range in an array-like object with a given
|
||||
* value.
|
||||
* @param {E} value - The `value` parameter in the `fill` method represents the element that will be
|
||||
* used to fill the specified range in the array.
|
||||
* @param [start=0] - The `start` parameter specifies the index at which to start filling the array
|
||||
* with the specified value. If not provided, it defaults to 0, indicating the beginning of the
|
||||
* array.
|
||||
* @param end - The `end` parameter in the `fill` function represents the index at which the filling
|
||||
* of values should stop. It specifies the end of the range within the array where the `value` should
|
||||
* be filled.
|
||||
* @returns The `fill` method is returning the modified object (`this`) after filling the specified
|
||||
* range with the provided value.
|
||||
*/
|
||||
fill(value: E, start = 0, end = this.length): this {
|
||||
// Handling negative indexes
|
||||
start = start < 0 ? this.length + start : start;
|
||||
end = end < 0 ? this.length + end : end;
|
||||
|
||||
// Boundary processing
|
||||
if (start < 0) start = 0;
|
||||
if (end > this.length) end = this.length;
|
||||
if (start >= end) return this;
|
||||
|
||||
// Iterate through the specified range and fill in the values
|
||||
for (let i = start; i < end; i++) {
|
||||
this.setAt(i, value);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
abstract setAt(index: number, value: E): boolean;
|
||||
|
||||
abstract override clone(): this;
|
||||
|
||||
abstract reverse(): this;
|
||||
|
||||
abstract push(elementOrNode: E | NODE): boolean;
|
||||
|
||||
abstract pushMany(elements: Iterable<E> | Iterable<R> | Iterable<NODE>): boolean[];
|
||||
|
||||
abstract delete(elementOrNode: E | NODE | undefined): boolean;
|
||||
|
||||
abstract at(index: number): E | undefined;
|
||||
|
||||
abstract deleteAt(pos: number): boolean;
|
||||
|
||||
abstract addAt(index: number, newElementOrNode: E | NODE): boolean;
|
||||
|
||||
protected abstract _createInstance(options?: LinearBaseOptions<E, R>): this;
|
||||
|
||||
protected abstract _getReverseIterator(...args: any[]): IterableIterator<E>;
|
||||
}
|
||||
|
||||
export abstract class LinearLinkedBase<E, R = any, NODE = any> extends LinearBase<E, R, NODE> {
|
||||
protected constructor(options?: LinearBaseOptions<E, R>) {
|
||||
super(options);
|
||||
if (options) {
|
||||
const { maxLen } = options;
|
||||
if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function overrides the indexOf method to improve performance by searching for an element in a
|
||||
* custom array implementation starting from a specified index.
|
||||
* @param {E} searchElement - The `searchElement` parameter is the element that you are searching for
|
||||
* within the array. The `indexOf` method will return the index of the first occurrence of this
|
||||
* element within the array.
|
||||
* @param {number} [fromIndex=0] - The `fromIndex` parameter in the `indexOf` method specifies the
|
||||
* index in the array at which to start the search for the `searchElement`. If provided, the search
|
||||
* will begin at the specified index and continue to the end of the array. If not provided, the
|
||||
* search will start at index
|
||||
* @returns The `indexOf` method is returning the index of the `searchElement` if it is found in the
|
||||
* array starting from the `fromIndex`. If the `searchElement` is not found, it returns -1.
|
||||
*/
|
||||
override indexOf(searchElement: E, fromIndex: number = 0): number {
|
||||
// In order to improve performance, it is best to override this method in the subclass of the array implementation
|
||||
const iterator = this._getIterator();
|
||||
let current = iterator.next();
|
||||
|
||||
let index = 0;
|
||||
while (index < fromIndex) {
|
||||
current = iterator.next();
|
||||
index++;
|
||||
}
|
||||
|
||||
while (!current.done) {
|
||||
if (current.value === searchElement) return index;
|
||||
current = iterator.next();
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function overrides the lastIndexOf method in TypeScript to improve performance by searching
|
||||
* for an element in reverse order starting from a specified index.
|
||||
* @param {E} searchElement - The `searchElement` parameter is the element that you want to find
|
||||
* within the array. The `lastIndexOf` method searches the array for this element starting from the
|
||||
* end of the array (or from the specified `fromIndex` if provided) and returns the index of the last
|
||||
* occurrence of the element
|
||||
* @param {number} fromIndex - The `fromIndex` parameter in the `lastIndexOf` method specifies the
|
||||
* index at which to start searching for the `searchElement` in the array. If provided, the search
|
||||
* will begin at this index and move towards the beginning of the array. If not provided, the search
|
||||
* will start at the
|
||||
* @returns The `lastIndexOf` method is being overridden to search for the `searchElement` starting
|
||||
* from the specified `fromIndex` (defaulting to the end of the array). It iterates over the array in
|
||||
* reverse order using a custom iterator `_getReverseIterator` and returns the index of the last
|
||||
* occurrence of the `searchElement` if found, or -1 if not found.
|
||||
*/
|
||||
override lastIndexOf(searchElement: E, fromIndex: number = this.length - 1): number {
|
||||
// In order to improve performance, it is best to override this method in the subclass of the array implementation
|
||||
const iterator = this._getReverseIterator();
|
||||
let current = iterator.next();
|
||||
|
||||
let index = this.length - 1;
|
||||
while (index > fromIndex) {
|
||||
current = iterator.next();
|
||||
index--;
|
||||
}
|
||||
|
||||
while (!current.done) {
|
||||
if (current.value === searchElement) return index;
|
||||
current = iterator.next();
|
||||
index--;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
override concat(...items: LinearBase<E, R>[]): this;
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n + m)
|
||||
* Space Complexity: O(n + m)
|
||||
*
|
||||
* The `concat` function in TypeScript overrides the default behavior to concatenate items into a new
|
||||
* list, handling both individual elements and instances of `LinearBase`.
|
||||
* @param {(E | LinearBase<E, R>)[]} items - The `concat` method you provided takes in a variable
|
||||
* number of arguments of type `E` or `LinearBase<E, R>`. The method concatenates these items to the
|
||||
* current list and returns a new list with the concatenated items.
|
||||
* @returns The `concat` method is returning a new instance of the class that it belongs to, with the
|
||||
* items passed as arguments concatenated to it.
|
||||
*/
|
||||
override concat(...items: (E | LinearBase<E, R>)[]): this {
|
||||
const newList = this.clone();
|
||||
|
||||
for (const item of items) {
|
||||
if (item instanceof LinearBase) {
|
||||
newList.pushMany(item);
|
||||
} else {
|
||||
newList.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return newList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n + m)
|
||||
* Space Complexity: O(m)
|
||||
*
|
||||
* The function overrides the splice method to handle deletion and insertion of elements in a data
|
||||
* structure while returning the removed elements.
|
||||
* @param {number} start - The `start` parameter in the `splice` method indicates the index at which
|
||||
* to start modifying the array.
|
||||
* @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the
|
||||
* number of elements to remove from the array starting at the specified `start` index. If
|
||||
* `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new
|
||||
* elements can still be inserted at
|
||||
* @param {E[]} items - The `items` parameter in the `splice` method represents the elements that
|
||||
* will be inserted into the array at the specified `start` index. These elements can be of any type
|
||||
* and there can be multiple elements passed as arguments to be inserted into the array.
|
||||
* @returns The `splice` method is returning a new instance of the data structure that was modified
|
||||
* by removing elements specified by the `start` and `deleteCount` parameters, and inserting new
|
||||
* elements provided in the `items` array.
|
||||
*/
|
||||
override splice(start: number, deleteCount: number = 0, ...items: E[]): this {
|
||||
start = start < 0 ? this.length + start : start;
|
||||
if (start < 0) start = 0;
|
||||
if (start > this.length) start = this.length;
|
||||
|
||||
const removedList = this._createInstance({ toElementFn: this._toElementFn });
|
||||
|
||||
// Move to starting position
|
||||
let currentNode = this.at(start);
|
||||
let currentIndex = start;
|
||||
|
||||
// Delete elements
|
||||
for (let i = 0; i < deleteCount && currentNode !== undefined; i++) {
|
||||
removedList.push(currentNode);
|
||||
this.delete(currentNode);
|
||||
currentNode = this.at(currentIndex); // Update node reference
|
||||
}
|
||||
|
||||
// Insert new element
|
||||
for (const item of items) {
|
||||
this.addAt(currentIndex, item);
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
return removedList;
|
||||
}
|
||||
|
||||
override reduceRight(callbackfn: ReduceLinearCallback<E>): E;
|
||||
|
||||
override reduceRight(callbackfn: ReduceLinearCallback<E>, initialValue: E): E;
|
||||
|
||||
override reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue: U): U;
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function `reduceRight` iterates over an array in reverse order and applies a callback function
|
||||
* to each element, accumulating a single result.
|
||||
* @param callbackfn - The `callbackfn` parameter is a function that will be called on each element
|
||||
* of the array from right to left. It takes four arguments:
|
||||
* @param {U} [initialValue] - The `initialValue` parameter is an optional value that is used as the
|
||||
* initial accumulator value in the reduce operation. If provided, the reduce operation starts with
|
||||
* this initial value and iterates over the elements of the array, applying the callback function to
|
||||
* each element and the current accumulator value. If `initial
|
||||
* @returns The `reduceRight` method is returning the final accumulated value after applying the
|
||||
* callback function to each element in the array from right to left.
|
||||
*/
|
||||
override reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue?: U): U {
|
||||
let accumulator = initialValue ?? (0 as U);
|
||||
let index = this.length - 1;
|
||||
for (const item of this._getReverseIterator()) {
|
||||
accumulator = callbackfn(accumulator, item, index--, this);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(m)
|
||||
* Space Complexity: O(m)
|
||||
*
|
||||
* The `slice` method is overridden to improve performance by creating a new instance and iterating
|
||||
* through the array to extract a subset based on the specified start and end indices.
|
||||
* @param {number} [start=0] - The `start` parameter in the `slice` method specifies the index at
|
||||
* which to begin extracting elements from the array. If no `start` parameter is provided, the
|
||||
* default value is 0, indicating that extraction should start from the beginning of the array.
|
||||
* @param {number} end - The `end` parameter in the `slice` method represents the index at which to
|
||||
* end the slicing of the array. If not provided, it defaults to the length of the array.
|
||||
* @returns The `slice` method is returning a new instance of the array implementation with elements
|
||||
* sliced from the original array based on the `start` and `end` parameters.
|
||||
*/
|
||||
override slice(start: number = 0, end: number = this.length): this {
|
||||
// In order to improve performance, it is best to override this method in the subclass of the array implementation
|
||||
start = start < 0 ? this.length + start : start;
|
||||
end = end < 0 ? this.length + end : end;
|
||||
|
||||
const newList = this._createInstance();
|
||||
const iterator = this._getIterator();
|
||||
let current = iterator.next();
|
||||
let c = 0;
|
||||
while (c < start) {
|
||||
current = iterator.next();
|
||||
c++;
|
||||
}
|
||||
for (let i = start; i < end; i++) {
|
||||
newList.push(current.value);
|
||||
current = iterator.next();
|
||||
}
|
||||
|
||||
return newList;
|
||||
}
|
||||
}
|
|
@ -185,7 +185,7 @@ import { IterableElementBase } from '../base';
|
|||
* ]);
|
||||
* console.log(scheduleTasks(tasks, 2)); // expectedMap
|
||||
*/
|
||||
export class Heap<E = any, R = any> extends IterableElementBase<E, R, Heap<E, R>> {
|
||||
export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
|
||||
/**
|
||||
* 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
|
||||
|
@ -416,17 +416,6 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R, Heap<E, R>
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* Convert the heap to an array.
|
||||
* @returns An array containing the elements of the heap.
|
||||
*/
|
||||
toArray(): E[] {
|
||||
return [...this.elements];
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
|
@ -483,7 +472,7 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R, Heap<E, R>
|
|||
* @returns The `filter` method is returning a new `Heap` object that contains the elements that pass
|
||||
* the filter condition specified by the `callback` function.
|
||||
*/
|
||||
filter(callback: ElementCallback<E, R, boolean, Heap<E, R>>, thisArg?: any): Heap<E, R> {
|
||||
filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): Heap<E, R> {
|
||||
const filteredList = new Heap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
|
@ -517,7 +506,7 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R, Heap<E, R>
|
|||
* @returns a new instance of the `Heap` class with the mapped elements.
|
||||
*/
|
||||
map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, Heap<E, R>>,
|
||||
callback: ElementCallback<E, R, EM>,
|
||||
comparator: Comparator<EM>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
|
|
|
@ -61,7 +61,7 @@ export class MaxHeap<E = any, R = any> extends Heap<E, R> {
|
|||
* @returns The `filter` method is returning a new `MaxHeap` object that contains the elements that pass
|
||||
* the filter condition specified by the `callback` function.
|
||||
*/
|
||||
override filter(callback: ElementCallback<E, R, boolean, MaxHeap<E, R>>, thisArg?: any): MaxHeap<E, R> {
|
||||
override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MaxHeap<E, R> {
|
||||
const filteredList = new MaxHeap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
|
@ -95,7 +95,7 @@ export class MaxHeap<E = any, R = any> extends Heap<E, R> {
|
|||
* @returns a new instance of the `MaxHeap` class with the mapped elements.
|
||||
*/
|
||||
override map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, MaxHeap<E, R>>,
|
||||
callback: ElementCallback<E, R, EM>,
|
||||
comparator: Comparator<EM>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
|
|
|
@ -49,7 +49,7 @@ export class MinHeap<E = any, R = any> extends Heap<E, R> {
|
|||
* @returns The `filter` method is returning a new `MinHeap` object that contains the elements that pass
|
||||
* the filter condition specified by the `callback` function.
|
||||
*/
|
||||
override filter(callback: ElementCallback<E, R, boolean, MinHeap<E, R>>, thisArg?: any): MinHeap<E, R> {
|
||||
override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MinHeap<E, R> {
|
||||
const filteredList = new MinHeap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
|
@ -83,7 +83,7 @@ export class MinHeap<E = any, R = any> extends Heap<E, R> {
|
|||
* @returns a new instance of the `MinHeap` class with the mapped elements.
|
||||
*/
|
||||
override map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, MinHeap<E, R>>,
|
||||
callback: ElementCallback<E, R, EM>,
|
||||
comparator: Comparator<EM>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
import type { DoublyLinkedListOptions, ElementCallback } from '../../types';
|
||||
import { IterableElementBase } from '../base';
|
||||
import { LinearLinkedBase } from '../base/linear-base';
|
||||
|
||||
export class DoublyLinkedListNode<E = any> {
|
||||
/**
|
||||
|
@ -22,60 +22,30 @@ export class DoublyLinkedListNode<E = any> {
|
|||
|
||||
protected _value: E;
|
||||
|
||||
/**
|
||||
* The function returns the value of a protected variable.
|
||||
* @returns The value of the variable `_value` is being returned.
|
||||
*/
|
||||
get value(): E {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The above function sets the value of a variable.
|
||||
* @param {E} value - The parameter "value" is of type E, which means it can be any type.
|
||||
*/
|
||||
set value(value: E) {
|
||||
this._value = value;
|
||||
}
|
||||
|
||||
protected _next: DoublyLinkedListNode<E> | undefined;
|
||||
|
||||
/**
|
||||
* The "next" function returns the next node in a doubly linked list.
|
||||
* @returns The `next` property is being returned. It can be either a `DoublyLinkedListNode<E>`
|
||||
* object or `undefined`.
|
||||
*/
|
||||
get next(): DoublyLinkedListNode<E> | undefined {
|
||||
return this._next;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "next" property of a DoublyLinkedListNode is set to the provided value.
|
||||
* @param {DoublyLinkedListNode<E> | undefined} value - The `value` parameter is of type
|
||||
* `DoublyLinkedListNode<E> | undefined`. This means that it can accept either a
|
||||
* `DoublyLinkedListNode` object or `undefined` as its value.
|
||||
*/
|
||||
set next(value: DoublyLinkedListNode<E> | undefined) {
|
||||
this._next = value;
|
||||
}
|
||||
|
||||
protected _prev: DoublyLinkedListNode<E> | undefined;
|
||||
|
||||
/**
|
||||
* The `prev` function returns the previous node in a doubly linked list.
|
||||
* @returns The `prev` property of the `DoublyLinkedListNode` class is being returned. It can either
|
||||
* be a `DoublyLinkedListNode` object or `undefined`.
|
||||
*/
|
||||
get prev(): DoublyLinkedListNode<E> | undefined {
|
||||
return this._prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the previous node of a doubly linked list node.
|
||||
* @param {DoublyLinkedListNode<E> | undefined} value - The `value` parameter is of type
|
||||
* `DoublyLinkedListNode<E> | undefined`. This means that it can accept either a
|
||||
* `DoublyLinkedListNode` object or `undefined` as its value.
|
||||
*/
|
||||
set prev(value: DoublyLinkedListNode<E> | undefined) {
|
||||
this._prev = value;
|
||||
}
|
||||
|
@ -513,7 +483,7 @@ export class DoublyLinkedListNode<E = any> {
|
|||
* scheduler.clear();
|
||||
* console.log(scheduler.listProcesses()); // []
|
||||
*/
|
||||
export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R, DoublyLinkedList<E, R>> {
|
||||
export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, DoublyLinkedListNode<E>> {
|
||||
/**
|
||||
* This TypeScript constructor initializes a DoublyLinkedList with optional elements and options.
|
||||
* @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the constructor is an
|
||||
|
@ -543,41 +513,22 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
|
||||
protected _head: DoublyLinkedListNode<E> | undefined;
|
||||
|
||||
/**
|
||||
* The `head` function returns the first node of a doubly linked list.
|
||||
* @returns The method `getHead()` returns either a `DoublyLinkedListNode<E>` object or `undefined`.
|
||||
*/
|
||||
get head(): DoublyLinkedListNode<E> | undefined {
|
||||
return this._head;
|
||||
}
|
||||
|
||||
protected _tail: DoublyLinkedListNode<E> | undefined;
|
||||
|
||||
/**
|
||||
* The `tail` function returns the last node of a doubly linked list.
|
||||
* @returns The `get tail()` method is returning either a `DoublyLinkedListNode<E>` object or
|
||||
* `undefined`.
|
||||
*/
|
||||
get tail(): DoublyLinkedListNode<E> | undefined {
|
||||
return this._tail;
|
||||
}
|
||||
|
||||
protected _length: number;
|
||||
|
||||
/**
|
||||
* The function returns the length of an object.
|
||||
* @returns The length of the object, which is a number.
|
||||
*/
|
||||
get length(): number {
|
||||
return this._length;
|
||||
}
|
||||
|
||||
protected _maxLen: number = -1;
|
||||
|
||||
get maxLen() {
|
||||
return this._maxLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -965,6 +916,28 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function `setAt` updates the value at a specified index in a data structure if the index
|
||||
* exists.
|
||||
* @param {number} index - The `index` parameter in the `setAt` method refers to the position in the
|
||||
* data structure where you want to set a new value.
|
||||
* @param {E} value - The `value` parameter in the `setAt` method represents the new value that you
|
||||
* want to set at the specified index in the data structure.
|
||||
* @returns The `setAt` method returns a boolean value - `true` if the value at the specified index
|
||||
* is successfully updated, and `false` if the index is out of bounds.
|
||||
*/
|
||||
setAt(index: number, value: E): boolean {
|
||||
const node = this.getNodeAt(index);
|
||||
if (node) {
|
||||
node.value = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -1051,31 +1024,6 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
this._length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* This function finds the index of a specified element, node, or predicate in a doubly linked list.
|
||||
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
||||
* elementNodeOrPredicate - The `indexOf` method takes in a parameter `elementNodeOrPredicate`, which
|
||||
* can be one of the following:
|
||||
* @returns The `indexOf` method returns the index of the element in the doubly linked list that
|
||||
* matches the provided element, node, or predicate. If no match is found, it returns -1.
|
||||
*/
|
||||
indexOf(elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)): number {
|
||||
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
||||
let index = 0;
|
||||
let current = this.head;
|
||||
while (current) {
|
||||
if (predicate(current)) {
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
current = current.next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -1142,40 +1090,6 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `toArray` function converts a linked list into an array.
|
||||
* @returns The `toArray()` method is returning an array of type `E[]`.
|
||||
*/
|
||||
toArray(): E[] {
|
||||
const array: E[] = [];
|
||||
let current = this.head;
|
||||
while (current) {
|
||||
array.push(current.value);
|
||||
current = current.next;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `toReversedArray` function converts a doubly linked list into an array in reverse order.
|
||||
* @returns The `toReversedArray()` function returns an array of type `E[]`.
|
||||
*/
|
||||
toReversedArray(): E[] {
|
||||
const array: E[] = [];
|
||||
let current = this.tail;
|
||||
while (current) {
|
||||
array.push(current.value);
|
||||
current = current.prev;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
|
@ -1185,8 +1099,8 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
* @returns The `clone()` method is returning a new instance of the `DoublyLinkedList` class, which
|
||||
* is a copy of the original list.
|
||||
*/
|
||||
clone(): DoublyLinkedList<E, R> {
|
||||
return new DoublyLinkedList<E, R>(this);
|
||||
clone(): this {
|
||||
return new DoublyLinkedList<E, R>(this, { toElementFn: this._toElementFn, maxLen: this._maxLen }) as this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1206,7 +1120,7 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
* @returns The `filter` method is returning a new `DoublyLinkedList` object that contains the
|
||||
* elements that pass the filter condition specified by the `callback` function.
|
||||
*/
|
||||
filter(callback: ElementCallback<E, R, boolean, DoublyLinkedList<E, R>>, thisArg?: any): DoublyLinkedList<E, R> {
|
||||
filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): DoublyLinkedList<E, R> {
|
||||
const filteredList = new DoublyLinkedList<E, R>([], { toElementFn: this.toElementFn });
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
|
@ -1239,7 +1153,7 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
* @returns a new instance of the `DoublyLinkedList` class with elements of type `T` and `RR`.
|
||||
*/
|
||||
map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, DoublyLinkedList<E, R>>,
|
||||
callback: ElementCallback<E, R, EM>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
): DoublyLinkedList<EM, RM> {
|
||||
|
@ -1339,4 +1253,30 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
|
||||
return (node: DoublyLinkedListNode<E>) => node.value === elementNodeOrPredicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function `_createInstance` returns a new instance of `DoublyLinkedList` with the specified
|
||||
* options.
|
||||
* @param [options] - The `options` parameter in the `_createInstance` method is of type
|
||||
* `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional
|
||||
* configuration options when creating a new instance of the `DoublyLinkedList` class.
|
||||
* @returns An instance of the `DoublyLinkedList` class with an empty array and the provided options
|
||||
* is being returned, cast as the current class type.
|
||||
*/
|
||||
protected override _createInstance(options?: DoublyLinkedListOptions<E, R>): this {
|
||||
return new DoublyLinkedList<E, R>([], options) as this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function returns an iterator that iterates over the elements of a data structure in reverse
|
||||
* order.
|
||||
*/
|
||||
protected *_getReverseIterator(): IterableIterator<E> {
|
||||
let current = this.tail;
|
||||
|
||||
while (current) {
|
||||
yield current.value;
|
||||
current = current.prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
import type { ElementCallback, SinglyLinkedListOptions } from '../../types';
|
||||
import { IterableElementBase } from '../base';
|
||||
import { LinearLinkedBase } from '../base/linear-base';
|
||||
|
||||
export class SinglyLinkedListNode<E = any> {
|
||||
/**
|
||||
|
@ -62,7 +62,7 @@ export class SinglyLinkedListNode<E = any> {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R, SinglyLinkedList<E, R>> {
|
||||
export class SinglyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, SinglyLinkedListNode<E>> {
|
||||
constructor(
|
||||
elements: Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>> = [],
|
||||
options?: SinglyLinkedListOptions<E, R>
|
||||
|
@ -70,8 +70,6 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
super(options);
|
||||
|
||||
if (options) {
|
||||
const { maxLen } = options;
|
||||
if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;
|
||||
}
|
||||
|
||||
this.pushMany(elements);
|
||||
|
@ -79,54 +77,26 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
|
||||
protected _head: SinglyLinkedListNode<E> | undefined;
|
||||
|
||||
/**
|
||||
* The `head` function returns the first node of a singly linked list.
|
||||
* @returns The method is returning either a SinglyLinkedListNode object or undefined.
|
||||
*/
|
||||
get head(): SinglyLinkedListNode<E> | undefined {
|
||||
return this._head;
|
||||
}
|
||||
|
||||
protected _tail: SinglyLinkedListNode<E> | undefined;
|
||||
|
||||
/**
|
||||
* The `tail` function returns the last node of a singly linked list.
|
||||
* @returns The method is returning either a SinglyLinkedListNode object or undefined.
|
||||
*/
|
||||
get tail(): SinglyLinkedListNode<E> | undefined {
|
||||
return this._tail;
|
||||
}
|
||||
|
||||
/**
|
||||
* The above function returns the value of the first element in a linked list, or undefined if the
|
||||
* list is empty.
|
||||
* @returns The value of the first node in the linked list, or undefined if the linked list is empty.
|
||||
*/
|
||||
get first(): E | undefined {
|
||||
return this.head?.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function returns the value of the last element in a linked list, or undefined if the list is
|
||||
* empty.
|
||||
* @returns The value of the last node in the linked list, or undefined if the linked list is empty.
|
||||
*/
|
||||
get last(): E | undefined {
|
||||
return this.tail?.value;
|
||||
}
|
||||
|
||||
protected _maxLen: number = -1;
|
||||
|
||||
get maxLen() {
|
||||
return this._maxLen;
|
||||
}
|
||||
|
||||
protected _length: number = 0;
|
||||
|
||||
/**
|
||||
* The function returns the length of an object.
|
||||
* @returns The length of the object, which is a number.
|
||||
*/
|
||||
get length(): number {
|
||||
return this._length;
|
||||
}
|
||||
|
@ -475,6 +445,29 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function setAt(index, value) updates the value at a specified index in a data structure if the
|
||||
* index exists.
|
||||
* @param {number} index - The `index` parameter in the `setAt` method refers to the position in the
|
||||
* data structure where you want to set a new value.
|
||||
* @param {E} value - The `value` parameter in the `setAt` method represents the new value that you
|
||||
* want to set at the specified index in the data structure.
|
||||
* @returns The `setAt` method returns a boolean value - `true` if the value at the specified index
|
||||
* is successfully updated, and `false` if the index is out of bounds (i.e., the node at that index
|
||||
* does not exist).
|
||||
*/
|
||||
setAt(index: number, value: E): boolean {
|
||||
const node = this.getNodeAt(index);
|
||||
if (node) {
|
||||
node.value = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -499,23 +492,6 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
this._length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `toArray` function converts a linked list into an array.
|
||||
* @returns The `toArray()` method is returning an array of type `E[]`.
|
||||
*/
|
||||
toArray(): E[] {
|
||||
const array: E[] = [];
|
||||
let current = this.head;
|
||||
while (current) {
|
||||
array.push(current.value);
|
||||
current = current.next;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -541,35 +517,6 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `indexOf` function in TypeScript searches for a specific element or node in a singly linked
|
||||
* list and returns its index if found.
|
||||
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
||||
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `indexOf` method can be one
|
||||
* of the following types:
|
||||
* @returns The `indexOf` method returns the index of the first occurrence of the element that
|
||||
* matches the provided predicate in the singly linked list. If no matching element is found, it
|
||||
* returns -1.
|
||||
*/
|
||||
indexOf(elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)): number {
|
||||
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
||||
let index = 0;
|
||||
let current = this.head;
|
||||
|
||||
while (current) {
|
||||
if (predicate(current)) {
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
current = current.next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -716,8 +663,8 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
* @returns The `clone()` method is returning a new instance of the `SinglyLinkedList` class, which
|
||||
* is a clone of the original list.
|
||||
*/
|
||||
clone(): SinglyLinkedList<E, R> {
|
||||
return new SinglyLinkedList<E, R>(this, { toElementFn: this.toElementFn });
|
||||
clone(): this {
|
||||
return new SinglyLinkedList<E, R>(this, { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -737,7 +684,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
* @returns The `filter` method is returning a new `SinglyLinkedList` object that contains the
|
||||
* elements that pass the filter condition specified by the `callback` function.
|
||||
*/
|
||||
filter(callback: ElementCallback<E, R, boolean, SinglyLinkedList<E, R>>, thisArg?: any): SinglyLinkedList<E, R> {
|
||||
filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): SinglyLinkedList<E, R> {
|
||||
const filteredList = new SinglyLinkedList<E, R>([], { toElementFn: this.toElementFn });
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
|
@ -770,7 +717,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
* @returns a new instance of the `SinglyLinkedList` class with the mapped elements.
|
||||
*/
|
||||
map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, SinglyLinkedList<E, R>>,
|
||||
callback: ElementCallback<E, R, EM>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
): SinglyLinkedList<EM, RM> {
|
||||
|
@ -844,4 +791,29 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|||
|
||||
return (node: SinglyLinkedListNode<E>) => node.value === elementNodeOrPredicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function `_createInstance` returns a new instance of `SinglyLinkedList` with the specified
|
||||
* options.
|
||||
* @param [options] - The `options` parameter in the `_createInstance` method is of type
|
||||
* `SinglyLinkedListOptions<E, R>`, which is used to configure the behavior of the `SinglyLinkedList`
|
||||
* instance being created. It is an optional parameter, meaning it can be omitted when calling the
|
||||
* method.
|
||||
* @returns An instance of the `SinglyLinkedList` class with an empty array and the provided options
|
||||
* is being returned.
|
||||
*/
|
||||
protected override _createInstance(options?: SinglyLinkedListOptions<E, R>): this {
|
||||
return new SinglyLinkedList<E, R>([], options) as this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function returns an iterator that iterates over the elements of a collection in reverse order.
|
||||
*/
|
||||
protected *_getReverseIterator(): IterableIterator<E> {
|
||||
const reversedArr = [...this].reverse();
|
||||
|
||||
for (const item of reversedArr) {
|
||||
yield item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,10 +64,7 @@ export class MaxPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {
|
|||
* @returns The `filter` method is returning a new `MaxPriorityQueue` object that contains the elements that pass
|
||||
* the filter condition specified by the `callback` function.
|
||||
*/
|
||||
override filter(
|
||||
callback: ElementCallback<E, R, boolean, MaxPriorityQueue<E, R>>,
|
||||
thisArg?: any
|
||||
): MaxPriorityQueue<E, R> {
|
||||
override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MaxPriorityQueue<E, R> {
|
||||
const filteredPriorityQueue = new MaxPriorityQueue<E, R>([], {
|
||||
toElementFn: this.toElementFn,
|
||||
comparator: this.comparator
|
||||
|
@ -104,7 +101,7 @@ export class MaxPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {
|
|||
* @returns a new instance of the `MaxPriorityQueue` class with the mapped elements.
|
||||
*/
|
||||
override map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, MaxPriorityQueue<E, R>>,
|
||||
callback: ElementCallback<E, R, EM>,
|
||||
comparator: Comparator<EM>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
|
|
|
@ -53,10 +53,7 @@ export class MinPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {
|
|||
* @returns The `filter` method is returning a new `MinPriorityQueue` object that contains the elements that pass
|
||||
* the filter condition specified by the `callback` function.
|
||||
*/
|
||||
override filter(
|
||||
callback: ElementCallback<E, R, boolean, MinPriorityQueue<E, R>>,
|
||||
thisArg?: any
|
||||
): MinPriorityQueue<E, R> {
|
||||
override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MinPriorityQueue<E, R> {
|
||||
const filteredPriorityQueue = new MinPriorityQueue<E, R>([], {
|
||||
toElementFn: this.toElementFn,
|
||||
comparator: this.comparator
|
||||
|
@ -93,7 +90,7 @@ export class MinPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {
|
|||
* @returns a new instance of the `MinPriorityQueue` class with the mapped elements.
|
||||
*/
|
||||
override map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, MinPriorityQueue<E, R>>,
|
||||
callback: ElementCallback<E, R, EM>,
|
||||
comparator: Comparator<EM>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
|
|
|
@ -55,7 +55,7 @@ export class PriorityQueue<E = any, R = any> extends Heap<E, R> {
|
|||
* @returns The `filter` method is returning a new `PriorityQueue` object that contains the elements that pass
|
||||
* the filter condition specified by the `callback` function.
|
||||
*/
|
||||
override filter(callback: ElementCallback<E, R, boolean, PriorityQueue<E, R>>, thisArg?: any): PriorityQueue<E, R> {
|
||||
override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): PriorityQueue<E, R> {
|
||||
const filteredPriorityQueue = new PriorityQueue<E, R>([], {
|
||||
toElementFn: this.toElementFn,
|
||||
comparator: this.comparator
|
||||
|
@ -92,7 +92,7 @@ export class PriorityQueue<E = any, R = any> extends Heap<E, R> {
|
|||
* @returns a new instance of the `PriorityQueue` class with the mapped elements.
|
||||
*/
|
||||
override map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, PriorityQueue<E, R>>,
|
||||
callback: ElementCallback<E, R, EM>,
|
||||
comparator: Comparator<EM>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
import type { DequeOptions, ElementCallback, IterableWithSizeOrLength } from '../../types';
|
||||
import { IterableElementBase } from '../base';
|
||||
import { calcMinUnitsRequired, rangeCheck } from '../../utils';
|
||||
import { LinearBase } from '../base/linear-base';
|
||||
|
||||
/**
|
||||
* 1. Operations at Both Ends: Supports adding and removing elements at both the front and back of the queue. This allows it to be used as a stack (last in, first out) and a queue (first in, first out).
|
||||
|
@ -104,7 +104,7 @@ import { calcMinUnitsRequired, rangeCheck } from '../../utils';
|
|||
* const k = 3;
|
||||
* console.log(maxSlidingWindow(nums, k)); // [3, 3, 5, 5, 6, 7]
|
||||
*/
|
||||
export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E, R>> {
|
||||
export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
||||
/**
|
||||
* The constructor initializes a Deque object with optional iterable of elements and options.
|
||||
* @param elements - An iterable object (such as an array or a Set) that contains the initial
|
||||
|
@ -120,9 +120,8 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
super(options);
|
||||
|
||||
if (options) {
|
||||
const { bucketSize, maxLen } = options;
|
||||
const { bucketSize } = options;
|
||||
if (typeof bucketSize === 'number') this._bucketSize = bucketSize;
|
||||
if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;
|
||||
}
|
||||
|
||||
let _size: number;
|
||||
|
@ -146,94 +145,48 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
|
||||
protected _bucketSize: number = 1 << 12;
|
||||
|
||||
/**
|
||||
* The bucketSize function returns the size of the bucket.
|
||||
*
|
||||
* @return The size of the bucket
|
||||
*/
|
||||
get bucketSize() {
|
||||
return this._bucketSize;
|
||||
}
|
||||
|
||||
protected _maxLen: number = -1;
|
||||
|
||||
/**
|
||||
* The maxLen function returns the max length of the deque.
|
||||
*
|
||||
* @return The max length of the deque
|
||||
*/
|
||||
get maxLen() {
|
||||
return this._maxLen;
|
||||
}
|
||||
|
||||
protected _bucketFirst = 0;
|
||||
|
||||
/**
|
||||
* The function returns the value of the protected variable `_bucketFirst`.
|
||||
* @returns The value of the `_bucketFirst` property.
|
||||
*/
|
||||
get bucketFirst(): number {
|
||||
return this._bucketFirst;
|
||||
}
|
||||
|
||||
protected _firstInBucket = 0;
|
||||
|
||||
/**
|
||||
* The function returns the value of the protected variable _firstInBucket.
|
||||
* @returns The method is returning the value of the variable `_firstInBucket`, which is of type
|
||||
* `number`.
|
||||
*/
|
||||
get firstInBucket(): number {
|
||||
return this._firstInBucket;
|
||||
}
|
||||
|
||||
protected _bucketLast = 0;
|
||||
|
||||
/**
|
||||
* The function returns the value of the protected variable `_bucketLast`.
|
||||
* @returns The value of the `_bucketLast` property, which is a number.
|
||||
*/
|
||||
get bucketLast(): number {
|
||||
return this._bucketLast;
|
||||
}
|
||||
|
||||
protected _lastInBucket = 0;
|
||||
|
||||
/**
|
||||
* The function returns the value of the protected variable _lastInBucket.
|
||||
* @returns The method is returning the value of the variable `_lastInBucket`, which is of type
|
||||
* `number`.
|
||||
*/
|
||||
get lastInBucket(): number {
|
||||
return this._lastInBucket;
|
||||
}
|
||||
|
||||
protected _bucketCount = 0;
|
||||
|
||||
/**
|
||||
* The function returns the number of buckets.
|
||||
* @returns The number of buckets.
|
||||
*/
|
||||
get bucketCount(): number {
|
||||
return this._bucketCount;
|
||||
}
|
||||
|
||||
protected _buckets: E[][] = [];
|
||||
|
||||
/**
|
||||
* The buckets function returns the buckets property of the object.
|
||||
* @return The buckets property
|
||||
*/
|
||||
get buckets() {
|
||||
return this._buckets;
|
||||
}
|
||||
|
||||
protected _length = 0;
|
||||
|
||||
/**
|
||||
* The length function returns the number of items in the stack.
|
||||
* @return The number of values in the set
|
||||
*/
|
||||
get length() {
|
||||
return this._length;
|
||||
}
|
||||
|
@ -443,29 +396,6 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
this._firstInBucket = this._lastInBucket = this._bucketSize >> 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The below function is a generator that yields elements from a collection one by one.
|
||||
*/
|
||||
*begin(): Generator<E> {
|
||||
let index = 0;
|
||||
while (index < this._length) {
|
||||
yield this.at(index);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The function `reverseBegin()` is a generator that yields elements in reverse order starting from
|
||||
* the last element.
|
||||
*/
|
||||
*reverseBegin(): Generator<E> {
|
||||
let index = this._length - 1;
|
||||
while (index >= 0) {
|
||||
yield this.at(index);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -658,6 +588,28 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
return true;
|
||||
}
|
||||
|
||||
// override indexOf(searchElement: E, fromIndex: number = 0): number {
|
||||
// let index = fromIndex;
|
||||
// let bucketIndex = this._bucketFirst;
|
||||
// let indexInBucket = this._firstInBucket + fromIndex;
|
||||
//
|
||||
// for (let i = 0; i < this._length; i++) {
|
||||
// if (this._buckets[bucketIndex][indexInBucket] === searchElement) {
|
||||
// return index;
|
||||
// }
|
||||
// index++;
|
||||
// indexInBucket++;
|
||||
// if (indexInBucket >= this._bucketSize) {
|
||||
// bucketIndex++;
|
||||
// indexInBucket = 0;
|
||||
// }
|
||||
// if (bucketIndex >= this._bucketCount) {
|
||||
// bucketIndex = 0;
|
||||
// }
|
||||
// }
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -704,28 +656,6 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n log n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `sort` function sorts the elements in a data structure using a provided comparator function.
|
||||
* @param [comparator] - The `comparator` parameter is a function that takes in two elements `x` and
|
||||
* `y` of type `E` and returns a number. The comparator function is used to determine the order of
|
||||
* the elements in the sorted array.
|
||||
* @returns Deque<E>
|
||||
*/
|
||||
sort(comparator?: (x: E, y: E) => number): this {
|
||||
const arr: E[] = [];
|
||||
for (let i = 0; i < this._length; ++i) {
|
||||
arr.push(this.at(i));
|
||||
}
|
||||
arr.sort(comparator);
|
||||
for (let i = 0; i < this._length; ++i) {
|
||||
this.setAt(i, arr[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
|
@ -756,37 +686,6 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
this._buckets = newBuckets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function "indexOf" returns the index of the first occurrence of a given element in an array,
|
||||
* or -1 if the element is not found.
|
||||
* @param {E} element - The "element" parameter represents the element that you want to find the
|
||||
* index of in the data structure.
|
||||
* @returns The indexOf function returns the index of the first occurrence of the specified element
|
||||
* in the data structure. If the element is not found, it returns -1.
|
||||
*/
|
||||
indexOf(element: E): number {
|
||||
for (let i = 0; i < this._length; ++i) {
|
||||
if (this.at(i) === element) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `toArray` function converts the elements of a data structure into an array.
|
||||
* @returns The `toArray()` method is returning an array of elements of type `E`.
|
||||
*/
|
||||
toArray(): E[] {
|
||||
return [...this];
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
|
@ -796,8 +695,12 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
* @returns The `clone()` method is returning a new instance of the `Deque` class with the same
|
||||
* elements as the original deque (`this`) and the same bucket size.
|
||||
*/
|
||||
clone(): Deque<E, R> {
|
||||
return new Deque<E, R>(this, { bucketSize: this.bucketSize, toElementFn: this.toElementFn });
|
||||
clone(): this {
|
||||
return new Deque<E, R>(this, {
|
||||
bucketSize: this.bucketSize,
|
||||
toElementFn: this.toElementFn,
|
||||
maxLen: this._maxLen
|
||||
}) as this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -816,7 +719,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
* @returns The `filter` method is returning a new `Deque` object that contains the elements that
|
||||
* satisfy the given predicate function.
|
||||
*/
|
||||
filter(predicate: ElementCallback<E, R, boolean, Deque<E, R>>, thisArg?: any): Deque<E, R> {
|
||||
filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Deque<E, R> {
|
||||
const newDeque = new Deque<E, R>([], { bucketSize: this._bucketSize, toElementFn: this.toElementFn });
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
|
@ -846,11 +749,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
* value of
|
||||
* @returns a new Deque object with elements of type EM and raw elements of type RM.
|
||||
*/
|
||||
map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, Deque<E, R>>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
): Deque<EM, RM> {
|
||||
map<EM, RM>(callback: ElementCallback<E, R, EM>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): Deque<EM, RM> {
|
||||
const newDeque = new Deque<EM, RM>([], { bucketSize: this._bucketSize, toElementFn });
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
|
@ -931,4 +830,26 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
|
|||
|
||||
return { bucketIndex, indexInBucket };
|
||||
}
|
||||
|
||||
/**
|
||||
* The function `_createInstance` returns a new instance of the `Deque` class with the specified
|
||||
* options.
|
||||
* @param [options] - The `options` parameter in the `_createInstance` method is of type
|
||||
* `DequeOptions<E, R>`, which is an optional parameter that allows you to pass additional
|
||||
* configuration options when creating a new instance of the `Deque` class.
|
||||
* @returns An instance of the `Deque` class with an empty array and the provided options, casted as
|
||||
* `this`.
|
||||
*/
|
||||
protected override _createInstance(options?: DequeOptions<E, R>): this {
|
||||
return new Deque<E, R>([], options) as this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns an iterator that iterates over elements in reverse order.
|
||||
*/
|
||||
protected *_getReverseIterator(): IterableIterator<E> {
|
||||
for (let i = this._length - 1; i > -1; i--) {
|
||||
yield this.at(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* @class
|
||||
*/
|
||||
import type { ElementCallback, QueueOptions } from '../../types';
|
||||
import { IterableElementBase } from '../base';
|
||||
import { SinglyLinkedList } from '../linked-list';
|
||||
import { LinearBase } from '../base/linear-base';
|
||||
|
||||
/**
|
||||
* 1. First In, First Out (FIFO): The core feature of a queue is its first in, first out nature. The element added to the queue first will be the one to be removed first.
|
||||
|
@ -16,14 +16,13 @@ import { SinglyLinkedList } from '../linked-list';
|
|||
* 6. Breadth-First Search (BFS): In traversal algorithms for graphs and trees, queues store elements that are to be visited.
|
||||
* 7. Real-time Queuing: Like queuing systems in banks or supermarkets.
|
||||
*/
|
||||
export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E, R>> {
|
||||
export class Queue<E = any, R = any> extends LinearBase<E, R> {
|
||||
constructor(elements: Iterable<E> | Iterable<R> = [], options?: QueueOptions<E, R>) {
|
||||
super(options);
|
||||
|
||||
if (options) {
|
||||
const { autoCompactRatio = 0.5, maxLen } = options;
|
||||
const { autoCompactRatio = 0.5 } = options;
|
||||
this._autoCompactRatio = autoCompactRatio;
|
||||
if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;
|
||||
}
|
||||
|
||||
this.pushMany(elements);
|
||||
|
@ -35,30 +34,26 @@ export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E,
|
|||
return this._elements;
|
||||
}
|
||||
|
||||
protected _maxLen: number = -1;
|
||||
|
||||
get maxLen() {
|
||||
return this._maxLen;
|
||||
}
|
||||
|
||||
protected _offset: number = 0;
|
||||
|
||||
/**
|
||||
* The offset function returns the offset of the current page.
|
||||
* @return The value of the protected variable _offset
|
||||
*/
|
||||
get offset(): number {
|
||||
return this._offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* The length function returns the number of elements in an array.
|
||||
* @returns {number} The length of the array, which is the difference between the length of the array and the offset.
|
||||
*/
|
||||
get length(): number {
|
||||
return this.elements.length - this.offset;
|
||||
}
|
||||
|
||||
protected _autoCompactRatio: number = 0.5;
|
||||
|
||||
get autoCompactRatio(): number {
|
||||
return this._autoCompactRatio;
|
||||
}
|
||||
|
||||
set autoCompactRatio(v: number) {
|
||||
this._autoCompactRatio = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -83,25 +78,6 @@ export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E,
|
|||
return this.length > 0 ? this.elements[this.elements.length - 1] : undefined;
|
||||
}
|
||||
|
||||
protected _autoCompactRatio: number = 0.5;
|
||||
|
||||
/**
|
||||
* This function returns the value of the autoCompactRatio property.
|
||||
* @returns The `autoCompactRatio` property of the object, which is a number.
|
||||
*/
|
||||
get autoCompactRatio(): number {
|
||||
return this._autoCompactRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* The above function sets the autoCompactRatio property to a specified number in TypeScript.
|
||||
* @param {number} v - The parameter `v` represents the value that will be assigned to the
|
||||
* `_autoCompactRatio` property.
|
||||
*/
|
||||
set autoCompactRatio(v: number) {
|
||||
this._autoCompactRatio = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
|
@ -209,6 +185,60 @@ export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E,
|
|||
return this.elements[index + this._offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `reverse` function in TypeScript reverses the elements of an array starting from a specified
|
||||
* offset.
|
||||
* @returns The `reverse()` method is returning the modified object itself (`this`) after reversing
|
||||
* the elements in the array and resetting the offset to 0.
|
||||
*/
|
||||
reverse(): this {
|
||||
this._elements = this.elements.slice(this.offset).reverse();
|
||||
this._offset = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function `addAt` inserts a new element at a specified index in an array, returning true if
|
||||
* successful and false if the index is out of bounds.
|
||||
* @param {number} index - The `index` parameter represents the position at which the `newElement`
|
||||
* should be added in the array.
|
||||
* @param {E} newElement - The `newElement` parameter represents the element that you want to insert
|
||||
* into the array at the specified index.
|
||||
* @returns The `addAt` method returns a boolean value - `true` if the new element was successfully
|
||||
* added at the specified index, and `false` if the index is out of bounds (less than 0 or greater
|
||||
* than the length of the array).
|
||||
*/
|
||||
addAt(index: number, newElement: E): boolean {
|
||||
if (index < 0 || index > this.length) return false;
|
||||
this._elements.splice(this.offset + index, 0, newElement);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function `setAt` updates an element at a specified index in an array-like data structure.
|
||||
* @param {number} index - The `index` parameter is a number that represents the position in the
|
||||
* array where the new element will be set.
|
||||
* @param {E} newElement - The `newElement` parameter represents the new value that you want to set
|
||||
* at the specified index in the array.
|
||||
* @returns The `setAt` method returns a boolean value - `true` if the element was successfully set
|
||||
* at the specified index, and `false` if the index is out of bounds (less than 0 or greater than the
|
||||
* length of the array).
|
||||
*/
|
||||
setAt(index: number, newElement: E): boolean {
|
||||
if (index < 0 || index > this.length) return false;
|
||||
this._elements[this.offset + index] = newElement;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -220,17 +250,6 @@ export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E,
|
|||
return this.length === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The toArray() function returns an array of elements from the current offset to the end of the _elements array.
|
||||
* @returns An array of type E is being returned.
|
||||
*/
|
||||
toArray(): E[] {
|
||||
return this.elements.slice(this.offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -263,8 +282,8 @@ export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E,
|
|||
* The `clone()` function returns a new Queue object with the same elements as the original Queue.
|
||||
* @returns The `clone()` method is returning a new instance of the `Queue` class.
|
||||
*/
|
||||
clone(): Queue<E, R> {
|
||||
return new Queue(this.elements.slice(this.offset), { toElementFn: this.toElementFn });
|
||||
clone(): this {
|
||||
return new Queue(this.elements.slice(this.offset), { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -283,7 +302,7 @@ export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E,
|
|||
* @returns The `filter` method is returning a new `Queue` object that contains the elements that
|
||||
* satisfy the given predicate function.
|
||||
*/
|
||||
filter(predicate: ElementCallback<E, R, boolean, Queue<E, R>>, thisArg?: any): Queue<E, R> {
|
||||
filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Queue<E, R> {
|
||||
const newDeque = new Queue<E, R>([], { toElementFn: this.toElementFn });
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
|
@ -313,11 +332,7 @@ export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E,
|
|||
* @returns A new Queue object containing elements of type EM, which are the result of applying the
|
||||
* callback function to each element in the original Queue object.
|
||||
*/
|
||||
map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, Queue<E, R>>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
): Queue<EM, RM> {
|
||||
map<EM, RM>(callback: ElementCallback<E, R, EM>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): Queue<EM, RM> {
|
||||
const newDeque = new Queue<EM, RM>([], { toElementFn });
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
|
@ -338,6 +353,30 @@ export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E,
|
|||
yield item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The function `_createInstance` returns a new instance of the `Queue` class with the specified
|
||||
* options.
|
||||
* @param [options] - The `options` parameter in the `_createInstance` method is of type
|
||||
* `QueueOptions<E, R>`, which is used to configure the behavior of the queue being created. It
|
||||
* allows you to specify settings or properties that can influence how the queue operates.
|
||||
* @returns An instance of the `Queue` class with an empty array and the provided options is being
|
||||
* returned.
|
||||
*/
|
||||
protected override _createInstance(options?: QueueOptions<E, R>): this {
|
||||
return new Queue<E, R>([], options) as this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function `_getReverseIterator` returns an iterator that iterates over elements in reverse
|
||||
* order.
|
||||
*/
|
||||
protected *_getReverseIterator(): IterableIterator<E> {
|
||||
for (let i = this.length - 1; i >= 0; i--) {
|
||||
const cur = this.at(i); // `at()` handles the offset.
|
||||
if (cur !== undefined) yield cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -355,7 +394,7 @@ export class LinkedListQueue<E = any, R = any> extends SinglyLinkedList<E, R> {
|
|||
* @returns The `clone()` method is returning a new instance of `LinkedListQueue` with the same
|
||||
* values as the original `LinkedListQueue`.
|
||||
*/
|
||||
override clone(): LinkedListQueue<E, R> {
|
||||
return new LinkedListQueue<E, R>(this, { toElementFn: this.toElementFn });
|
||||
override clone(): this {
|
||||
return new LinkedListQueue<E, R>(this, { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import { IterableElementBase } from '../base';
|
|||
* 5. Expression Evaluation: Used for the evaluation of arithmetic or logical expressions, especially when dealing with parenthesis matching and operator precedence.
|
||||
* 6. Backtracking Algorithms: In problems where multiple branches need to be explored but only one branch can be explored at a time, stacks can be used to save the state at each branching point.
|
||||
*/
|
||||
export class Stack<E = any, R = any> extends IterableElementBase<E, R, Stack<E, R>> {
|
||||
export class Stack<E = any, R = any> extends IterableElementBase<E, R> {
|
||||
constructor(elements: Iterable<E> | Iterable<R> = [], options?: StackOptions<E, R>) {
|
||||
super(options);
|
||||
this.pushMany(elements);
|
||||
|
@ -153,17 +153,6 @@ export class Stack<E = any, R = any> extends IterableElementBase<E, R, Stack<E,
|
|||
return spliced.length === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The toArray function returns a copy of the elements in an array.
|
||||
* @returns An array of type E.
|
||||
*/
|
||||
toArray(): E[] {
|
||||
return this.elements.slice();
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -201,7 +190,7 @@ export class Stack<E = any, R = any> extends IterableElementBase<E, R, Stack<E,
|
|||
* @returns The `filter` method is returning a new `Stack` object that contains the elements that
|
||||
* satisfy the given predicate function.
|
||||
*/
|
||||
filter(predicate: ElementCallback<E, R, boolean, Stack<E, R>>, thisArg?: any): Stack<E, R> {
|
||||
filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Stack<E, R> {
|
||||
const newStack = new Stack<E, R>([], { toElementFn: this.toElementFn });
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
|
@ -230,11 +219,7 @@ export class Stack<E = any, R = any> extends IterableElementBase<E, R, Stack<E,
|
|||
* value of
|
||||
* @returns a new Stack object with elements of type EM and raw elements of type RM.
|
||||
*/
|
||||
map<EM, RM>(
|
||||
callback: ElementCallback<E, R, EM, Stack<E, R>>,
|
||||
toElementFn?: (rawElement: RM) => EM,
|
||||
thisArg?: any
|
||||
): Stack<EM, RM> {
|
||||
map<EM, RM>(callback: ElementCallback<E, R, EM>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): Stack<EM, RM> {
|
||||
const newStack = new Stack<EM, RM>([], { toElementFn });
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
|
|
|
@ -170,7 +170,7 @@ export class TrieNode {
|
|||
* const subnet = ip.split('.').slice(0, 3).join('.');
|
||||
* console.log(ipRoutingTable.hasPrefix(subnet)); // true
|
||||
*/
|
||||
export class Trie<R = any> extends IterableElementBase<string, R, Trie<R>> {
|
||||
export class Trie<R = any> extends IterableElementBase<string, R> {
|
||||
/**
|
||||
* The constructor initializes a Trie data structure with optional options and words provided as
|
||||
* input.
|
||||
|
@ -545,7 +545,7 @@ export class Trie<R = any> extends IterableElementBase<string, R, Trie<R>> {
|
|||
* specific object as the context for the `predicate` function. If `thisArg` is provided, it will be
|
||||
* @returns The `filter` method is returning an array of strings (`string[]`).
|
||||
*/
|
||||
filter(predicate: ElementCallback<string, R, boolean, Trie<R>>, thisArg?: any): Trie<R> {
|
||||
filter(predicate: ElementCallback<string, R, boolean>, thisArg?: any): Trie<R> {
|
||||
const results = new Trie<R>([], { toElementFn: this.toElementFn, caseSensitive: this.caseSensitive });
|
||||
let index = 0;
|
||||
for (const word of this) {
|
||||
|
@ -576,7 +576,7 @@ export class Trie<R = any> extends IterableElementBase<string, R, Trie<R>> {
|
|||
* @returns a new Trie object.
|
||||
*/
|
||||
map<RM>(
|
||||
callback: ElementCallback<string, R, string, Trie<R>>,
|
||||
callback: ElementCallback<string, R, string>,
|
||||
toElementFn?: (rawElement: RM) => string,
|
||||
thisArg?: any
|
||||
): Trie<RM> {
|
||||
|
@ -609,6 +609,10 @@ export class Trie<R = any> extends IterableElementBase<string, R, Trie<R>> {
|
|||
yield* _dfs(this.root, '');
|
||||
}
|
||||
|
||||
protected get _total() {
|
||||
return this._size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(l), where l is the length of the input string.
|
||||
* Space Complexity: O(1) - Constant space.
|
||||
|
|
|
@ -1,25 +1,34 @@
|
|||
import { IterableElementBase, IterableEntryBase } from '../../../data-structures';
|
||||
import { LinearBase } from '../../../data-structures/base/linear-base';
|
||||
|
||||
export type EntryCallback<K, V, R> = (key: K, value: V, index: number, container: IterableEntryBase<K, V>) => R;
|
||||
export type ElementCallback<E, R, RT, C> = (element: E, index: number, container: IterableElementBase<E, R, C>) => RT;
|
||||
export type EntryCallback<K, V, R> = (key: K, value: V, index: number, original: IterableEntryBase<K, V>) => R;
|
||||
export type ElementCallback<E, R, RT> = (element: E, index: number, original: IterableElementBase<E, R>) => RT;
|
||||
export type ReduceEntryCallback<K, V, R> = (
|
||||
accumulator: R,
|
||||
value: V,
|
||||
key: K,
|
||||
index: number,
|
||||
container: IterableEntryBase<K, V>
|
||||
original: IterableEntryBase<K, V>
|
||||
) => R;
|
||||
export type ReduceElementCallback<E, R, RT, C> = (
|
||||
|
||||
export type ReduceElementCallback<E, R, RT = E> = (
|
||||
accumulator: RT,
|
||||
element: E,
|
||||
index: number,
|
||||
container: IterableElementBase<E, R, C>
|
||||
original: IterableElementBase<E, R>
|
||||
) => RT;
|
||||
|
||||
// export type IterableEntryBaseOptions<K, V, R> = {
|
||||
// toEntryFn?: (rawElement: R) => BTNEntry<K, V>;
|
||||
// };
|
||||
export type ReduceLinearCallback<E, RT = E> = (
|
||||
accumulator: RT,
|
||||
element: E,
|
||||
index: number,
|
||||
original: LinearBase<E>
|
||||
) => RT;
|
||||
|
||||
export type IterableElementBaseOptions<E, R> = {
|
||||
toElementFn?: (rawElement: R) => E;
|
||||
};
|
||||
|
||||
export type LinearBaseOptions<E, R> = IterableElementBaseOptions<E, R> & {
|
||||
maxLen?: number;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { IterableElementBaseOptions } from '../base';
|
||||
import { LinearBaseOptions } from '../base';
|
||||
|
||||
export type DoublyLinkedListOptions<E, R> = IterableElementBaseOptions<E, R> & {
|
||||
maxLen?: number;
|
||||
};
|
||||
export type DoublyLinkedListOptions<E, R> = LinearBaseOptions<E, R> & {};
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { IterableElementBaseOptions } from '../base';
|
||||
import { LinearBaseOptions } from '../base';
|
||||
|
||||
export type SinglyLinkedListOptions<E, R> = IterableElementBaseOptions<E, R> & {
|
||||
maxLen?: number;
|
||||
};
|
||||
export type SinglyLinkedListOptions<E, R> = LinearBaseOptions<E, R> & {};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { IterableElementBaseOptions } from '../base';
|
||||
import { LinearBaseOptions } from '../base';
|
||||
|
||||
export type DequeOptions<E, R> = {
|
||||
bucketSize?: number;
|
||||
maxLen?: number;
|
||||
} & IterableElementBaseOptions<E, R>;
|
||||
} & LinearBaseOptions<E, R>;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { IterableElementBaseOptions } from '../base';
|
||||
import { LinearBaseOptions } from '../base';
|
||||
|
||||
export type QueueOptions<E, R> = IterableElementBaseOptions<E, R> & {
|
||||
export type QueueOptions<E, R> = LinearBaseOptions<E, R> & {
|
||||
autoCompactRatio?: number;
|
||||
maxLen?: number;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { DoublyLinkedList, DoublyLinkedListNode, SinglyLinkedList } from '../../../../src';
|
||||
import { DoublyLinkedList, DoublyLinkedListNode } from '../../../../src';
|
||||
|
||||
describe('DoublyLinkedListNode', () => {
|
||||
it('should DoublyLinkedListNode', () => {
|
||||
|
@ -466,6 +466,95 @@ describe('DoublyLinkedList Operation Test', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('DoublyLinkedList Additional Methods', () => {
|
||||
// Slice method implementation and test
|
||||
test('slice should return a new list with specified range', () => {
|
||||
const list = new DoublyLinkedList([1, 2, 3, 4, 5]);
|
||||
const slicedList = list.slice(1, 4);
|
||||
|
||||
expect(slicedList.toArray()).toEqual([2, 3, 4]);
|
||||
expect(list.length).toBe(5); // Original list unchanged
|
||||
});
|
||||
|
||||
// Splice method implementation
|
||||
test('splice should modify list and return removed elements', () => {
|
||||
const list = new DoublyLinkedList([1, 2, 3, 4, 5]);
|
||||
const removedList = list.splice(2, 2, 6, 7);
|
||||
|
||||
expect(list.toArray()).toEqual([1, 2, 6, 7, 5]);
|
||||
expect(removedList.toArray()).toEqual([3, 4]);
|
||||
});
|
||||
|
||||
// Concat method test
|
||||
test('concat should combine multiple lists', () => {
|
||||
const list1 = new DoublyLinkedList([1, 2]);
|
||||
const list2 = new DoublyLinkedList([3, 4]);
|
||||
const list3 = new DoublyLinkedList([5, 6]);
|
||||
|
||||
const concatenatedList = list1.concat(list2, list3);
|
||||
expect(concatenatedList.toArray()).toEqual([1, 2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
// Sort method test
|
||||
test('sort should order elements in ascending order', () => {
|
||||
const list = new DoublyLinkedList([5, 2, 8, 1, 9]);
|
||||
list.sort((a, b) => a - b);
|
||||
|
||||
expect(list.toArray()).toEqual([1, 2, 5, 8, 9]);
|
||||
});
|
||||
|
||||
// Reverse method test
|
||||
test('reverse should invert the list order', () => {
|
||||
const list = new DoublyLinkedList([1, 2, 3, 4, 5]);
|
||||
list.reverse();
|
||||
|
||||
expect(list.toArray()).toEqual([5, 4, 3, 2, 1]);
|
||||
});
|
||||
|
||||
// Join method test
|
||||
test('join should convert list to string with separator', () => {
|
||||
const list = new DoublyLinkedList(['a', 'b', 'c']);
|
||||
|
||||
expect(list.join('-')).toBe('a-b-c');
|
||||
expect(list.join()).toBe('a,b,c');
|
||||
});
|
||||
|
||||
// IndexOf method test
|
||||
test('indexOf should return first occurrence index', () => {
|
||||
const list = new DoublyLinkedList([1, 2, 3, 2, 1]);
|
||||
|
||||
expect(list.indexOf(2)).toBe(1);
|
||||
expect(list.indexOf(4)).toBe(-1);
|
||||
});
|
||||
|
||||
// LastIndexOf method test
|
||||
test('lastIndexOf should return last occurrence index', () => {
|
||||
const list = new DoublyLinkedList([1, 2, 3, 2, 1]);
|
||||
|
||||
expect(list.lastIndexOf(2)).toBe(3);
|
||||
expect(list.lastIndexOf(4)).toBe(-1);
|
||||
});
|
||||
|
||||
// findIndex method test
|
||||
test('findIndex should return first occurrence index', () => {
|
||||
const list = new DoublyLinkedList([1, 2, 3, 2, 1]);
|
||||
expect(list.findIndex(item => item === 2)).toBe(1);
|
||||
expect(list.findIndex(item => item === 4)).toBe(-1);
|
||||
});
|
||||
|
||||
// fill method test
|
||||
test('fill should return fill all the list', () => {
|
||||
let list = new DoublyLinkedList([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9)]).toEqual([9, 9, 9, 9, 9]);
|
||||
list = new DoublyLinkedList([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, 2, 3)]).toEqual([1, 2, 9, 2, 1]);
|
||||
list = new DoublyLinkedList([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, -3, -2)]).toEqual([1, 2, 9, 2, 1]);
|
||||
list = new DoublyLinkedList([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, -2, -3)]).toEqual([1, 2, 3, 2, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('iterable methods', () => {
|
||||
it('should forEach, some, every, filter, map, reduce of the deque', () => {
|
||||
const dl = new DoublyLinkedList<number>();
|
||||
|
|
|
@ -458,6 +458,95 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('SinglyLinkedList Additional Methods', () => {
|
||||
// Slice method implementation and test
|
||||
test('slice should return a new list with specified range', () => {
|
||||
const list = new SinglyLinkedList([1, 2, 3, 4, 5]);
|
||||
const slicedList = list.slice(1, 4);
|
||||
|
||||
expect(slicedList.toArray()).toEqual([2, 3, 4]);
|
||||
expect(list.length).toBe(5); // Original list unchanged
|
||||
});
|
||||
|
||||
// Splice method implementation
|
||||
test('splice should modify list and return removed elements', () => {
|
||||
const list = new SinglyLinkedList([1, 2, 3, 4, 5]);
|
||||
const removedList = list.splice(2, 2, 6, 7);
|
||||
|
||||
expect(list.toArray()).toEqual([1, 2, 6, 7, 5]);
|
||||
expect(removedList.toArray()).toEqual([3, 4]);
|
||||
});
|
||||
|
||||
// Concat method test
|
||||
test('concat should combine multiple lists', () => {
|
||||
const list1 = new SinglyLinkedList([1, 2]);
|
||||
const list2 = new SinglyLinkedList([3, 4]);
|
||||
const list3 = new SinglyLinkedList([5, 6]);
|
||||
|
||||
const concatenatedList = list1.concat(list2, list3);
|
||||
expect(concatenatedList.toArray()).toEqual([1, 2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
// Sort method test
|
||||
test('sort should order elements in ascending order', () => {
|
||||
const list = new SinglyLinkedList([5, 2, 8, 1, 9]);
|
||||
list.sort((a, b) => a - b);
|
||||
|
||||
expect(list.toArray()).toEqual([1, 2, 5, 8, 9]);
|
||||
});
|
||||
|
||||
// Reverse method test
|
||||
test('reverse should invert the list order', () => {
|
||||
const list = new SinglyLinkedList([1, 2, 3, 4, 5]);
|
||||
list.reverse();
|
||||
|
||||
expect(list.toArray()).toEqual([5, 4, 3, 2, 1]);
|
||||
});
|
||||
|
||||
// Join method test
|
||||
test('join should convert list to string with separator', () => {
|
||||
const list = new SinglyLinkedList(['a', 'b', 'c']);
|
||||
|
||||
expect(list.join('-')).toBe('a-b-c');
|
||||
expect(list.join()).toBe('a,b,c');
|
||||
});
|
||||
|
||||
// IndexOf method test
|
||||
test('indexOf should return first occurrence index', () => {
|
||||
const list = new SinglyLinkedList([1, 2, 3, 2, 1]);
|
||||
|
||||
expect(list.indexOf(2)).toBe(1);
|
||||
expect(list.indexOf(4)).toBe(-1);
|
||||
});
|
||||
|
||||
// LastIndexOf method test
|
||||
test('lastIndexOf should return last occurrence index', () => {
|
||||
const list = new SinglyLinkedList([1, 2, 3, 2, 1]);
|
||||
|
||||
expect(list.lastIndexOf(2)).toBe(3);
|
||||
expect(list.lastIndexOf(4)).toBe(-1);
|
||||
});
|
||||
|
||||
// findIndex method test
|
||||
test('findIndex should return first occurrence index', () => {
|
||||
const list = new SinglyLinkedList([1, 2, 3, 2, 1]);
|
||||
expect(list.findIndex(item => item === 2)).toBe(1);
|
||||
expect(list.findIndex(item => item === 4)).toBe(-1);
|
||||
});
|
||||
|
||||
// fill method test
|
||||
test('fill should return fill all the list', () => {
|
||||
let list = new SinglyLinkedList([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9)]).toEqual([9, 9, 9, 9, 9]);
|
||||
list = new SinglyLinkedList([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, 2, 3)]).toEqual([1, 2, 9, 2, 1]);
|
||||
list = new SinglyLinkedList([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, -3, -2)]).toEqual([1, 2, 9, 2, 1]);
|
||||
list = new SinglyLinkedList([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, -2, -3)]).toEqual([1, 2, 3, 2, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SinglyLinkedList', () => {
|
||||
let list: SinglyLinkedList<number>;
|
||||
|
||||
|
@ -555,7 +644,8 @@ describe('iterable methods', () => {
|
|||
expect(sl.some(element => element > 2)).toBe(true);
|
||||
|
||||
expect([...sl.filter(element => element > 2)]).toEqual([3]);
|
||||
expect([...sl.map(element => element * 2)]).toEqual([2, 4, 6]);
|
||||
const mappedSl = sl.map(element => element * 2);
|
||||
expect([...mappedSl]).toEqual([2, 4, 6]);
|
||||
expect(sl.reduce((accumulator, element) => accumulator + element, 0)).toEqual(6);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -382,21 +382,21 @@ describe('Deque - Additional Operations', () => {
|
|||
expect(deque.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('begin should yield elements from the beginning', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
const iterator = deque.begin();
|
||||
expect(iterator.next().value).toBe(1);
|
||||
expect(iterator.next().value).toBe(2);
|
||||
});
|
||||
// it('begin should yield elements from the beginning', () => {
|
||||
// deque.push(1);
|
||||
// deque.push(2);
|
||||
// const iterator = deque.begin();
|
||||
// expect(iterator.next().value).toBe(1);
|
||||
// expect(iterator.next().value).toBe(2);
|
||||
// });
|
||||
|
||||
it('reverseBegin should yield elements in reverse order', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
const iterator = deque.reverseBegin();
|
||||
expect(iterator.next().value).toBe(2);
|
||||
expect(iterator.next().value).toBe(1);
|
||||
});
|
||||
// it('reverseBegin should yield elements in reverse order', () => {
|
||||
// deque.push(1);
|
||||
// deque.push(2);
|
||||
// const iterator = deque.reverseBegin();
|
||||
// expect(iterator.next().value).toBe(2);
|
||||
// expect(iterator.next().value).toBe(1);
|
||||
// });
|
||||
});
|
||||
describe('Deque - push Method', () => {
|
||||
let deque: Deque<number>;
|
||||
|
@ -543,6 +543,95 @@ describe('Deque - shift Method', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Deque Additional Methods', () => {
|
||||
// Slice method implementation and test
|
||||
test('slice should return a new list with specified range', () => {
|
||||
const list = new Deque([1, 2, 3, 4, 5]);
|
||||
const slicedList = list.slice(1, 4);
|
||||
|
||||
expect(slicedList.toArray()).toEqual([2, 3, 4]);
|
||||
expect(list.length).toBe(5); // Original list unchanged
|
||||
});
|
||||
|
||||
// Splice method implementation
|
||||
test('splice should modify list and return removed elements', () => {
|
||||
const list = new Deque([1, 2, 3, 4, 5]);
|
||||
const removedList = list.splice(2, 2, 6, 7);
|
||||
|
||||
expect(list.toArray()).toEqual([1, 2, 6, 7, 5]);
|
||||
expect(removedList.toArray()).toEqual([3, 4]);
|
||||
});
|
||||
|
||||
// Concat method test
|
||||
test('concat should combine multiple lists', () => {
|
||||
const list1 = new Deque([1, 2]);
|
||||
const list2 = new Deque([3, 4]);
|
||||
const list3 = new Deque([5, 6]);
|
||||
|
||||
const concatenatedList = list1.concat(list2, list3);
|
||||
expect(concatenatedList.toArray()).toEqual([1, 2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
// Sort method test
|
||||
test('sort should order elements in ascending order', () => {
|
||||
const list = new Deque([5, 2, 8, 1, 9]);
|
||||
list.sort((a, b) => a - b);
|
||||
|
||||
expect(list.toArray()).toEqual([1, 2, 5, 8, 9]);
|
||||
});
|
||||
|
||||
// Reverse method test
|
||||
test('reverse should invert the list order', () => {
|
||||
const list = new Deque([1, 2, 3, 4, 5]);
|
||||
list.reverse();
|
||||
|
||||
expect(list.toArray()).toEqual([5, 4, 3, 2, 1]);
|
||||
});
|
||||
|
||||
// Join method test
|
||||
test('join should convert list to string with separator', () => {
|
||||
const list = new Deque(['a', 'b', 'c']);
|
||||
|
||||
expect(list.join('-')).toBe('a-b-c');
|
||||
expect(list.join()).toBe('a,b,c');
|
||||
});
|
||||
|
||||
// IndexOf method test
|
||||
test('indexOf should return first occurrence index', () => {
|
||||
const list = new Deque([1, 2, 3, 2, 1]);
|
||||
|
||||
expect(list.indexOf(2)).toBe(1);
|
||||
expect(list.indexOf(4)).toBe(-1);
|
||||
});
|
||||
|
||||
// LastIndexOf method test
|
||||
test('lastIndexOf should return last occurrence index', () => {
|
||||
const list = new Deque([1, 2, 3, 2, 1]);
|
||||
|
||||
expect(list.lastIndexOf(2)).toBe(3);
|
||||
expect(list.lastIndexOf(4)).toBe(-1);
|
||||
});
|
||||
|
||||
// findIndex method test
|
||||
test('findIndex should return first occurrence index', () => {
|
||||
const list = new Deque([1, 2, 3, 2, 1]);
|
||||
expect(list.findIndex(item => item === 2)).toBe(1);
|
||||
expect(list.findIndex(item => item === 4)).toBe(-1);
|
||||
});
|
||||
|
||||
// fill method test
|
||||
test('fill should return fill all the list', () => {
|
||||
let list = new Deque([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9)]).toEqual([9, 9, 9, 9, 9]);
|
||||
list = new Deque([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, 2, 3)]).toEqual([1, 2, 9, 2, 1]);
|
||||
list = new Deque([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, -3, -2)]).toEqual([1, 2, 9, 2, 1]);
|
||||
list = new Deque([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, -2, -3)]).toEqual([1, 2, 3, 2, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Deque', () => {
|
||||
it('should initialize with default iterable with length function', () => {
|
||||
class IterableNumbers {
|
||||
|
|
|
@ -298,6 +298,95 @@ describe('Queue - Additional Methods', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Queue Additional Methods', () => {
|
||||
// Slice method implementation and test
|
||||
test('slice should return a new list with specified range', () => {
|
||||
const list = new Queue([1, 2, 3, 4, 5]);
|
||||
const slicedList = list.slice(1, 4);
|
||||
|
||||
expect(slicedList.toArray()).toEqual([2, 3, 4]);
|
||||
expect(list.length).toBe(5); // Original list unchanged
|
||||
});
|
||||
|
||||
// Splice method implementation
|
||||
test('splice should modify list and return removed elements', () => {
|
||||
const list = new Queue([1, 2, 3, 4, 5]);
|
||||
const removedList = list.splice(2, 2, 6, 7);
|
||||
|
||||
expect(list.toArray()).toEqual([1, 2, 6, 7, 5]);
|
||||
expect(removedList.toArray()).toEqual([3, 4]);
|
||||
});
|
||||
|
||||
// Concat method test
|
||||
test('concat should combine multiple lists', () => {
|
||||
const list1 = new Queue([1, 2]);
|
||||
const list2 = new Queue([3, 4]);
|
||||
const list3 = new Queue([5, 6]);
|
||||
|
||||
const concatenatedList = list1.concat(list2, list3);
|
||||
expect(concatenatedList.toArray()).toEqual([1, 2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
// Sort method test
|
||||
test('sort should order elements in ascending order', () => {
|
||||
const list = new Queue([5, 2, 8, 1, 9]);
|
||||
list.sort((a, b) => a - b);
|
||||
|
||||
expect(list.toArray()).toEqual([1, 2, 5, 8, 9]);
|
||||
});
|
||||
|
||||
// Reverse method test
|
||||
test('reverse should invert the list order', () => {
|
||||
const list = new Queue([1, 2, 3, 4, 5]);
|
||||
list.reverse();
|
||||
|
||||
expect(list.toArray()).toEqual([5, 4, 3, 2, 1]);
|
||||
});
|
||||
|
||||
// Join method test
|
||||
test('join should convert list to string with separator', () => {
|
||||
const list = new Queue(['a', 'b', 'c']);
|
||||
|
||||
expect(list.join('-')).toBe('a-b-c');
|
||||
expect(list.join()).toBe('a,b,c');
|
||||
});
|
||||
|
||||
// IndexOf method test
|
||||
test('indexOf should return first occurrence index', () => {
|
||||
const list = new Queue([1, 2, 3, 2, 1]);
|
||||
|
||||
expect(list.indexOf(2)).toBe(1);
|
||||
expect(list.indexOf(4)).toBe(-1);
|
||||
});
|
||||
|
||||
// LastIndexOf method test
|
||||
test('lastIndexOf should return last occurrence index', () => {
|
||||
const list = new Queue([1, 2, 3, 2, 1]);
|
||||
|
||||
expect(list.lastIndexOf(2)).toBe(3);
|
||||
expect(list.lastIndexOf(4)).toBe(-1);
|
||||
});
|
||||
|
||||
// findIndex method test
|
||||
test('findIndex should return first occurrence index', () => {
|
||||
const list = new Queue([1, 2, 3, 2, 1]);
|
||||
expect(list.findIndex(item => item === 2)).toBe(1);
|
||||
expect(list.findIndex(item => item === 4)).toBe(-1);
|
||||
});
|
||||
|
||||
// fill method test
|
||||
test('fill should return fill all the list', () => {
|
||||
let list = new Queue([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9)]).toEqual([9, 9, 9, 9, 9]);
|
||||
list = new Queue([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, 2, 3)]).toEqual([1, 2, 9, 2, 1]);
|
||||
list = new Queue([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, -3, -2)]).toEqual([1, 2, 9, 2, 1]);
|
||||
list = new Queue([1, 2, 3, 2, 1]);
|
||||
expect([...list.fill(9, -2, -3)]).toEqual([1, 2, 3, 2, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Queue - Static and Clone Methods', () => {
|
||||
it('fromArray should create a new queue from an array', () => {
|
||||
const array = [1, 2, 3];
|
||||
|
|
Loading…
Reference in a new issue