fix: #114. feat: Enhanced SinglyLinkedList methods to support Node type parameters for push, unshift, addAfter, addBefore, getNode, addAt, delete, indexOf; added a new get method.

This commit is contained in:
Revone 2024-11-20 22:07:42 +13:00
parent 09a5d8a11a
commit fde5af1f1c
5 changed files with 274 additions and 149 deletions

View file

@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file.
- [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
- [`auto-changelog`](https://github.com/CookPete/auto-changelog)
## [v1.53.4](https://github.com/zrwusa/data-structure-typed/compare/v1.51.5...main) (upcoming)
## [v1.53.5](https://github.com/zrwusa/data-structure-typed/compare/v1.51.5...main) (upcoming)
### Changes

52
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "data-structure-typed",
"version": "1.53.4",
"version": "1.53.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "data-structure-typed",
"version": "1.53.4",
"version": "1.53.5",
"license": "MIT",
"devDependencies": {
"@eslint/compat": "^1.2.2",
@ -19,11 +19,11 @@
"@typescript-eslint/eslint-plugin": "^8.12.1",
"@typescript-eslint/parser": "^8.12.1",
"auto-changelog": "^2.5.0",
"avl-tree-typed": "^1.53.3",
"avl-tree-typed": "^1.53.4",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.53.3",
"bst-typed": "^1.53.3",
"data-structure-typed": "^1.53.3",
"binary-tree-typed": "^1.53.4",
"bst-typed": "^1.53.4",
"data-structure-typed": "^1.53.4",
"dependency-cruiser": "^16.5.0",
"doctoc": "^2.2.1",
"eslint": "^9.13.0",
@ -32,7 +32,7 @@
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"fast-glob": "^3.3.2",
"heap-typed": "^1.53.3",
"heap-typed": "^1.53.4",
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",
@ -3437,13 +3437,13 @@
}
},
"node_modules/avl-tree-typed": {
"version": "1.53.3",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.53.3.tgz",
"integrity": "sha512-cDJlPy25fa2ry8oWt8W1h9ijBGYm8hvbf+CGyi6WrcZ9hvUbJV0zfdladdL8un6S5vyMU2PT57W1H7uqhHBqMQ==",
"version": "1.53.4",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.53.4.tgz",
"integrity": "sha512-dZMEutl5xMp/n54V6W6SugCXdmfcgy+6esqlpjG47nQfrQ3WMQzx2oytMWRZa6Y+nDtDNefbwlEOO/fLKZUHyQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.53.3"
"data-structure-typed": "^1.53.4"
}
},
"node_modules/babel-jest": {
@ -3602,13 +3602,13 @@
}
},
"node_modules/binary-tree-typed": {
"version": "1.53.3",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.53.3.tgz",
"integrity": "sha512-pyjbqPkaw7RnQE9KJUpIEdiQU9o0ZfwtQTflCr9/40segAF6tZ8Llf6JMB0n7tg1CHW3Ru6k0FOEamc7BXJKug==",
"version": "1.53.4",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.53.4.tgz",
"integrity": "sha512-/yDQUWHdT1HQBkMVTGZuo+Nn/nx1JnV5ERBFIKCdDVBvG2qKmTa5RlSC7rnjLzLsQz28qVHvisjoRYBhcQpCWg==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.53.3"
"data-structure-typed": "^1.53.4"
}
},
"node_modules/brace-expansion": {
@ -3691,13 +3691,13 @@
}
},
"node_modules/bst-typed": {
"version": "1.53.3",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.53.3.tgz",
"integrity": "sha512-qgI2TFaK9o9M00Td632glUzFJYRfjiPICHvQY5btzv3QzT+KUhZqBmqEtbwwx8qFHJy/Wz96sFMUx/PlfbYioQ==",
"version": "1.53.4",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.53.4.tgz",
"integrity": "sha512-hjTK/CcW2hw0yAtazhFOl7lsNq598FuNwCgbcjpFgXk51swLwJ5P5Sm70UzwVns1LSdIulTK49zil9tGs6zv1g==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.53.3"
"data-structure-typed": "^1.53.4"
}
},
"node_modules/buffer-from": {
@ -4069,9 +4069,9 @@
}
},
"node_modules/data-structure-typed": {
"version": "1.53.3",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.53.3.tgz",
"integrity": "sha512-hIfGCq40JOjqoZ8CjwTZgdi76ow7gn1LUPDpeDoQ47v6yiWDPA7kkOd8AmGaqBFSKhkBbGPa85ipg28u/zpRKw==",
"version": "1.53.4",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.53.4.tgz",
"integrity": "sha512-sMmlWv2wMqUVPnBemYc7RQMYtM0AXQq0m9drVeu0eMtpSvojvFb4hW+hzpd6IBtULguNw2YBG9EyNo7irlpavQ==",
"dev": true,
"license": "MIT"
},
@ -5946,13 +5946,13 @@
}
},
"node_modules/heap-typed": {
"version": "1.53.3",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.53.3.tgz",
"integrity": "sha512-eISjbd808zDUhJ1azWIlkLXQgGj6IOasO8yGAhI/NOkQ/Y3J9+5k3gx3llMoyiL5XQKbZ5+tHtoqQ4bfSELjVg==",
"version": "1.53.4",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.53.4.tgz",
"integrity": "sha512-/lktvgpfH7Y2q8XpMFYCEebRIo5nM85DCR19zUeo3soVrxa2H90vJAKJJ0cPP/DEJ2cDggMk/Cuo4k4LLhbf7A==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.53.3"
"data-structure-typed": "^1.53.4"
}
},
"node_modules/html-escaper": {

View file

@ -70,11 +70,11 @@
"@typescript-eslint/eslint-plugin": "^8.12.1",
"@typescript-eslint/parser": "^8.12.1",
"auto-changelog": "^2.5.0",
"avl-tree-typed": "^1.53.3",
"avl-tree-typed": "^1.53.4",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.53.3",
"bst-typed": "^1.53.3",
"data-structure-typed": "^1.53.3",
"binary-tree-typed": "^1.53.4",
"bst-typed": "^1.53.4",
"data-structure-typed": "^1.53.4",
"dependency-cruiser": "^16.5.0",
"doctoc": "^2.2.1",
"eslint": "^9.13.0",
@ -83,7 +83,7 @@
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"fast-glob": "^3.3.2",
"heap-typed": "^1.53.3",
"heap-typed": "^1.53.4",
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",

View file

@ -819,13 +819,7 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
existingElementOrNode: E | DoublyLinkedListNode<E>,
newElementOrNode: E | DoublyLinkedListNode<E>
): boolean {
let existingNode;
if (existingElementOrNode instanceof DoublyLinkedListNode) {
existingNode = existingElementOrNode;
} else {
existingNode = this.getNode(existingElementOrNode);
}
const existingNode: DoublyLinkedListNode<E> | undefined = this.getNode(existingElementOrNode);
if (existingNode) {
const newNode = this._ensureNode(newElementOrNode);
@ -862,13 +856,7 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* was not found in the linked list.
*/
addAfter(existingElementOrNode: E | DoublyLinkedListNode<E>, newElementOrNode: E | DoublyLinkedListNode<E>): boolean {
let existingNode;
if (existingElementOrNode instanceof DoublyLinkedListNode) {
existingNode = existingElementOrNode;
} else {
existingNode = this.getNode(existingElementOrNode);
}
const existingNode: DoublyLinkedListNode<E> | undefined = this.getNode(existingElementOrNode);
if (existingNode) {
const newNode = this._ensureNode(newElementOrNode);
@ -978,17 +966,15 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* Time Complexity: O(n)
* Space Complexity: O(1)
*
* The indexOf function in TypeScript returns the index of a specified element or node in a Doubly
* Linked List.
* @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the
* `indexOf` method can be either an element of type `E` or a `DoublyLinkedListNode` containing an
* element of type `E`.
* @returns The `indexOf` method is returning the index of the element or node in the doubly linked
* list. If the element or node is found in the list, the method returns the index of that element or
* node. If the element or node is not found in the list, the method returns -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 - 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(elementOrNode: E | DoublyLinkedListNode<E>): number {
const predicate = this._ensurePredicate(elementOrNode);
indexOf(elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)): number {
const predicate = this._ensurePredicate(elementNodeOrPredicate);
let index = 0;
let current = this.head;
while (current) {
@ -1005,8 +991,6 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* Time Complexity: O(n)
* Space Complexity: O(1)
*
*/
/**
* This function retrieves an element from a doubly linked list based on a given element
* node or predicate.
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
@ -1180,6 +1164,26 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
return mappedList;
}
/**
* Time Complexity: O(n)
* Space Complexity: O(1)
*
*/
countOccurrences(elementOrNode: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)): number {
const predicate = this._ensurePredicate(elementOrNode);
let count = 0;
let current = this.head;
while (current) {
if (predicate(current)) {
count++;
}
current = current.next;
}
return count;
}
/**
* Time Complexity: O(n)
* Space Complexity: O(n)

View file

@ -121,34 +121,17 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
return this._size;
}
/**
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The `fromArray` function creates a new SinglyLinkedList instance and populates it with the elements from the given
* array.
* @param {E[]} data - The `data` parameter is an array of elements of type `E`.
* @returns The `fromArray` function returns a `SinglyLinkedList` object.
*/
static fromArray<E>(data: E[]) {
const singlyLinkedList = new SinglyLinkedList<E>();
for (const item of data) {
singlyLinkedList.push(item);
}
return singlyLinkedList;
}
/**
* Time Complexity: O(1)
* Space Complexity: O(1)
*
* The push function adds a new element to the end of a singly linked list.
* @param {E} element - The "element" parameter represents the value of the element that you want to
* add to the linked list.
* @returns The `push` method is returning a boolean value, `true`.
* The `push` function adds a new element or node to the end of a singly linked list.
* @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the `push`
* method can accept either an element of type `E` or a `SinglyLinkedListNode<E>` object.
* @returns The `push` method is returning a boolean value, specifically `true`.
*/
push(element: E): boolean {
const newNode = new SinglyLinkedListNode(element);
push(elementOrNode: E | SinglyLinkedListNode<E>): boolean {
const newNode = this._ensureNode(elementOrNode);
if (!this.head) {
this._head = newNode;
this._tail = newNode;
@ -208,13 +191,15 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* Time Complexity: O(1)
* Space Complexity: O(1)
*
* The unshift function adds a new element to the beginning of a singly linked list.
* @param {E} element - The "element" parameter represents the value of the element that you want to
* add to the beginning of the singly linked list.
* @returns The `unshift` method is returning a boolean value, `true`.
* The unshift function adds a new element or node to the beginning of a singly linked list in
* TypeScript.
* @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the
* `unshift` method can be either an element of type `E` or a `SinglyLinkedListNode` containing an
* element of type `E`.
* @returns The `unshift` method is returning a boolean value, specifically `true`.
*/
unshift(element: E): boolean {
const newNode = new SinglyLinkedListNode(element);
unshift(elementOrNode: E | SinglyLinkedListNode<E>): boolean {
const newNode = this._ensureNode(elementOrNode);
if (!this.head) {
this._head = newNode;
this._tail = newNode;
@ -226,6 +211,30 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
return true;
}
/**
* Time Complexity: O(n)
* Space Complexity: O(1)
*
* This function searches for a specific element in a singly linked list based on a given node or
* predicate.
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `get` method can be one of
* the following types:
* @returns The `get` method returns the value of the first node in the singly linked list that
* satisfies the provided predicate function. If no such node is found, it returns `undefined`.
*/
get(
elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)
): E | undefined {
const predicate = this._ensurePredicate(elementNodeOrPredicate);
let current = this.head;
while (current) {
if (predicate(current)) return current.value;
current = current.next;
}
return undefined;
}
/**
* Time Complexity: O(n)
* Space Complexity: O(1)
@ -245,6 +254,25 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
return current!.value;
}
/**
* Time Complexity: O(1)
* Space Complexity: O(1)
*
* The function `isNode` in TypeScript checks if the input is an instance of `SinglyLinkedListNode`.
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can be
* one of the following types:
* @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an
* instance of `SinglyLinkedListNode<E>`. If it is, the function returns `true`, indicating that the
* parameter is a `SinglyLinkedListNode<E>`. If it is not an instance of `SinglyLinkedListNode<E>`,
* the function returns `false`.
*/
isNode(
elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)
): elementNodeOrPredicate is SinglyLinkedListNode<E> {
return elementNodeOrPredicate instanceof SinglyLinkedListNode;
}
/**
* Time Complexity: O(n)
* Space Complexity: O(1)
@ -296,18 +324,18 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* Space Complexity: O(1)
*
* The delete function removes a node with a specific value from a singly linked list.
* @param {E | SinglyLinkedListNode<E>} valueOrNode - The `valueOrNode` parameter can accept either a value of type `E`
* @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can accept either a value of type `E`
* or a `SinglyLinkedListNode<E>` object.
* @returns The `delete` method returns a boolean value. It returns `true` if the value or node is found and
* successfully deleted from the linked list, and `false` if the value or node is not found in the linked list.
*/
delete(valueOrNode: E | SinglyLinkedListNode<E> | undefined): boolean {
if (valueOrNode === undefined) return false;
delete(elementOrNode: E | SinglyLinkedListNode<E> | undefined): boolean {
if (elementOrNode === undefined) return false;
let value: E;
if (valueOrNode instanceof SinglyLinkedListNode) {
value = valueOrNode.value;
if (elementOrNode instanceof SinglyLinkedListNode) {
value = elementOrNode.value;
} else {
value = valueOrNode;
value = elementOrNode;
}
let current = this.head,
prev = undefined;
@ -339,26 +367,30 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* Time Complexity: O(n)
* Space Complexity: O(1)
*
* The `addAt` function inserts a value at a specified index in a singly linked list.
* @param {number} index - The index parameter represents the position at which the new value should be inserted in the
* linked list. It is of type number.
* @param {E} value - The `value` parameter represents the value that you want to insert into the linked list at the
* specified index.
* @returns The `insert` method returns a boolean value. It returns `true` if the insertion is successful, and `false`
* if the index is out of bounds.
* The `addAt` function inserts a new element or node at a specified index in a singly linked list.
* @param {number} index - The `index` parameter represents the position at which you want to add a
* new element or node in the linked list. It is a number that indicates the index where the new
* element or node should be inserted.
* @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
* `addAt` method can be either a value of type `E` or a `SinglyLinkedListNode<E>` object. This
* parameter represents the element or node that you want to add to the linked list at the specified
* index.
* @returns The `addAt` method returns a boolean value - `true` if the element or node was
* successfully added at the specified index, and `false` if the index is out of bounds.
*/
addAt(index: number, value: E): boolean {
addAt(index: number, newElementOrNode: E | SinglyLinkedListNode<E>): boolean {
if (index < 0 || index > this._size) return false;
if (index === 0) {
this.unshift(value);
this.unshift(newElementOrNode);
return true;
}
if (index === this._size) {
this.push(value);
this.push(newElementOrNode);
return true;
}
const newNode = new SinglyLinkedListNode(value);
const newNode = this._ensureNode(newElementOrNode);
const prevNode = this.getNodeAt(index - 1);
newNode.next = prevNode!.next;
prevNode!.next = newNode;
@ -430,17 +462,22 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* Time Complexity: O(n)
* Space Complexity: O(1)
*
* The `indexOf` function returns the index of the first occurrence of a given value in a linked list.
* @param {E} value - The value parameter is the value that you want to find the index of in the linked list.
* @returns The method is returning the index of the first occurrence of the specified value in the linked list. If the
* value is not found, it returns -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(value: E): number {
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 (current.value === value) {
if (predicate(current)) {
return index;
}
index++;
@ -454,17 +491,24 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* Time Complexity: O(n)
* Space Complexity: O(1)
*
* The function finds a node in a singly linked list by its value and returns the node if found, otherwise returns
* undefined.
* @param {E} value - The value parameter is the value that we want to search for in the linked list.
* @returns a `SinglyLinkedListNode<E>` if a node with the specified value is found in the linked list. If no node with
* the specified value is found, the function returns `undefined`.
* The function `getNode` in TypeScript searches for a node in a singly linked list based on a given
* element, node, or predicate.
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean) | undefined} elementNodeOrPredicate
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getNode` method can be one
* of the following types:
* @returns The `getNode` method returns either a `SinglyLinkedListNode<E>` if a matching node is
* found based on the provided predicate, or it returns `undefined` if no matching node is found or
* if the input parameter is `undefined`.
*/
getNode(value: E): SinglyLinkedListNode<E> | undefined {
getNode(
elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean) | undefined
): SinglyLinkedListNode<E> | undefined {
if (elementNodeOrPredicate === undefined) return;
const predicate = this._ensurePredicate(elementNodeOrPredicate);
let current = this.head;
while (current) {
if (current.value === value) {
if (predicate(current)) {
return current;
}
current = current.next;
@ -477,31 +521,39 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* Time Complexity: O(n)
* Space Complexity: O(1)
*
* The `addBefore` function inserts a new value before an existing value in a singly linked list.
* @param {E | SinglyLinkedListNode<E>} existingValueOrNode - The existing value or node that you want to insert the
* new value before. It can be either the value itself or a node containing the value in the linked list.
* @param {E} newValue - The `newValue` parameter represents the value that you want to insert into the linked list.
* @returns The method `addBefore` returns a boolean value. It returns `true` if the new value was successfully
* inserted before the existing value, and `false` otherwise.
* The function `addBefore` in TypeScript adds a new element or node before an existing element or
* node in a singly linked list.
* @param {E | SinglyLinkedListNode<E>} existingElementOrNode - existingElementOrNode represents the
* element or node in the linked list before which you want to add a new element or node.
* @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
* `addBefore` method represents the element or node that you want to insert before the existing
* element or node in the linked list. This new element can be of type `E` or a
* `SinglyLinkedListNode<E>`.
* @returns The `addBefore` method returns a boolean value - `true` if the new element or node was
* successfully added before the existing element or node, and `false` if the operation was
* unsuccessful.
*/
addBefore(existingValueOrNode: E | SinglyLinkedListNode<E>, newValue: E): boolean {
addBefore(
existingElementOrNode: E | SinglyLinkedListNode<E>,
newElementOrNode: E | SinglyLinkedListNode<E>
): boolean {
if (!this.head) return false;
let existingValue: E;
if (existingValueOrNode instanceof SinglyLinkedListNode) {
existingValue = existingValueOrNode.value;
if (this.isNode(existingElementOrNode)) {
existingValue = existingElementOrNode.value;
} else {
existingValue = existingValueOrNode;
existingValue = existingElementOrNode;
}
if (this.head.value === existingValue) {
this.unshift(newValue);
this.unshift(newElementOrNode);
return true;
}
let current = this.head;
while (current.next) {
if (current.next.value === existingValue) {
const newNode = new SinglyLinkedListNode(newValue);
const newNode = this._ensureNode(newElementOrNode);
newNode.next = current.next;
current.next = newNode;
this._size++;
@ -517,24 +569,23 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* Time Complexity: O(n)
* Space Complexity: O(1)
*
* The `addAfter` function inserts a new node with a given value after an existing node in a singly linked list.
* @param {E | SinglyLinkedListNode<E>} existingValueOrNode - The existing value or node in the linked list after which
* the new value will be inserted. It can be either the value of the existing node or the existing node itself.
* @param {E} newValue - The value that you want to insert into the linked list after the existing value or node.
* @returns The method returns a boolean value. It returns true if the new value was successfully inserted after the
* existing value or node, and false if the existing value or node was not found in the linked list.
* The `addAfter` function in TypeScript adds a new element or node after an existing element or node
* in a singly linked list.
* @param {E | SinglyLinkedListNode<E>} existingElementOrNode - existingElementOrNode can be either
* an element of type E or a SinglyLinkedListNode of type E.
* @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
* `addAfter` method represents the element or node that you want to add after the existing element
* or node in a singly linked list. This parameter can be either the value of the new element or a
* reference to a `SinglyLinkedListNode` containing
* @returns The `addAfter` method returns a boolean value - `true` if the new element or node was
* successfully added after the existing element or node, and `false` if the existing element or node
* was not found.
*/
addAfter(existingValueOrNode: E | SinglyLinkedListNode<E>, newValue: E): boolean {
let existingNode: E | SinglyLinkedListNode<E> | undefined;
if (existingValueOrNode instanceof SinglyLinkedListNode) {
existingNode = existingValueOrNode;
} else {
existingNode = this.getNode(existingValueOrNode);
}
addAfter(existingElementOrNode: E | SinglyLinkedListNode<E>, newElementOrNode: E | SinglyLinkedListNode<E>): boolean {
const existingNode: SinglyLinkedListNode<E> | undefined = this.getNode(existingElementOrNode);
if (existingNode) {
const newNode = new SinglyLinkedListNode(newValue);
const newNode = this._ensureNode(newElementOrNode);
newNode.next = existingNode.next;
existingNode.next = newNode;
if (existingNode === this.tail) {
@ -551,16 +602,20 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* Time Complexity: O(n)
* Space Complexity: O(1)
*
* The function counts the number of occurrences of a given value in a linked list.
* @param {E} value - The value parameter is the value that you want to count the occurrences of in the linked list.
* @returns The count of occurrences of the given value in the linked list.
* The function `countOccurrences` iterates through a singly linked list and counts the occurrences
* of a specified element or nodes that satisfy a given predicate.
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementOrNode
* - The `elementOrNode` parameter in the `countOccurrences` method can accept three types of values:
* @returns The `countOccurrences` method returns the number of occurrences of the specified element,
* node, or predicate function in the singly linked list.
*/
countOccurrences(value: E): number {
countOccurrences(elementOrNode: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)): number {
const predicate = this._ensurePredicate(elementOrNode);
let count = 0;
let current = this.head;
while (current) {
if (current.value === value) {
if (predicate(current)) {
count++;
}
current = current.next;
@ -657,4 +712,70 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
current = current.next;
}
}
/**
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The `fromArray` function creates a new SinglyLinkedList instance and populates it with the elements from the given
* array.
* @param {E[]} data - The `data` parameter is an array of elements of type `E`.
* @returns The `fromArray` function returns a `SinglyLinkedList` object.
*/
static fromArray<E>(data: E[]) {
const singlyLinkedList = new SinglyLinkedList<E>();
for (const item of data) {
singlyLinkedList.push(item);
}
return singlyLinkedList;
}
/**
* The _isPredicate function in TypeScript checks if the input is a function that takes a
* SinglyLinkedListNode as an argument and returns a boolean.
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following types:
* @returns The _isPredicate method is returning a boolean value based on whether the
* elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a
* function, the method will return true, indicating that it is a predicate function. If it is not a
* function, the method will return false.
*/
protected _isPredicate(
elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)
): elementNodeOrPredicate is (node: SinglyLinkedListNode<E>) => boolean {
return typeof elementNodeOrPredicate === 'function';
}
/**
* The function `_ensureNode` ensures that the input is a valid node and returns it, creating a new
* node if necessary.
* @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can be either
* an element of type `E` or a `SinglyLinkedListNode` containing an element of type `E`.
* @returns A SinglyLinkedListNode<E> object is being returned.
*/
protected _ensureNode(elementOrNode: E | SinglyLinkedListNode<E>) {
if (this.isNode(elementOrNode)) return elementOrNode;
return new SinglyLinkedListNode<E>(elementOrNode);
}
/**
* The function `_ensurePredicate` in TypeScript ensures that the input is either a node, a predicate
* function, or a value to compare with the node's value.
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following types:
* @returns A function is being returned. If the input `elementNodeOrPredicate` is already a node, a
* function is returned that checks if a given node is equal to the input node. If the input is a
* predicate function, it is returned as is. If the input is neither a node nor a predicate function,
* a function is returned that checks if a given node's value is equal to the input
*/
protected _ensurePredicate(
elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)
) {
if (this.isNode(elementNodeOrPredicate)) return (node: SinglyLinkedListNode<E>) => node === elementNodeOrPredicate;
if (this._isPredicate(elementNodeOrPredicate)) return elementNodeOrPredicate;
return (node: SinglyLinkedListNode<E>) => node.value === elementNodeOrPredicate;
}
}