From 4747839d881bc43a22ca2d893acb6aef9c12366a Mon Sep 17 00:00:00 2001 From: Revone Date: Tue, 9 Jan 2024 12:04:50 +0800 Subject: [PATCH] Refactor: Standardize addition and removal methods for all sequential data structures to push, pop, shift, unshift. --- CHANGELOG.md | 2 +- README.md | 114 +++++++++++----- SPECIFICATION.md | 4 +- SPECIFICATION_zh-CN.md | 81 ++++++++++++ SPONSOR-zh-CN.md => SPONSOR_zh-CN.md | 2 +- .../linked-list/doubly-linked-list.ts | 110 +++------------- .../linked-list/singly-linked-list.ts | 122 +++++------------- src/data-structures/queue/deque.ts | 67 ---------- src/data-structures/queue/queue.ts | 98 -------------- .../linked-list/doubly-linked-list.test.ts | 12 +- .../linked-list/singly-linked-list.test.ts | 20 +-- .../linked-list/skip-list.test.ts | 8 +- test/unit/data-structures/queue/deque.test.ts | 52 ++++---- test/unit/data-structures/queue/queue.test.ts | 40 +++--- 14 files changed, 285 insertions(+), 447 deletions(-) create mode 100644 SPECIFICATION_zh-CN.md rename SPONSOR-zh-CN.md => SPONSOR_zh-CN.md (97%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 085b277..428fdb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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.50.3](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) +## [v1.50.4](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) ### Changes diff --git a/README.md b/README.md index 461ab5d..acaa87f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # data-structure-typed - ![npm](https://img.shields.io/npm/dm/data-structure-typed) ![GitHub contributors](https://img.shields.io/github/contributors/zrwusa/data-structure-typed) ![npm package minimized gzipped size (select exports)](https://img.shields.io/bundlejs/size/data-structure-typed) @@ -17,7 +16,8 @@ ## Why Do you envy C++ with [STL]() (std::), Python with [collections](), and Java with [java.util]() ? Well, no need to envy -anymore! JavaScript and TypeScript now have [data-structure-typed]().**`Benchmark`** compared with C++ STL. **`API standards`** aligned with ES6 and Java. **`Usability`** is comparable to Python +anymore! JavaScript and TypeScript now have [data-structure-typed]().**`Benchmark`** compared with C++ STL. * +*`API standards`** aligned with ES6 and Java. **`Usability`** is comparable to Python [//]: # (![Branches](https://img.shields.io/badge/branches-55.47%25-red.svg?style=flat)) @@ -28,13 +28,15 @@ anymore! JavaScript and TypeScript now have [data-structure-typed]().**`Benchmar [//]: # (![Lines](https://img.shields.io/badge/lines-68.6%25-red.svg?style=flat)) -### We provide data structures that are not available in JS/TS +### Data structures available -Heap, Binary Tree, Red Black Tree, Linked List, Deque, Trie, Directed Graph, Undirected Graph, BST, AVL Tree, Priority Queue, Queue, Tree Multiset. +We provide data structures that are not available in JS/TS +Heap, Binary Tree, Red Black Tree, Linked List, Deque, Trie, Directed Graph, Undirected Graph, BST, AVL Tree, Priority +Queue, Queue, Tree Multiset. +### Performance -### Performance surpasses that of native JS/TS - +Performance surpasses that of native JS/TS @@ -99,6 +101,53 @@ Heap, Binary Tree, Red Black Tree, Linked List, Deque, Trie, Directed Graph, Und
+### Conciseness and uniformity +In Java.utils, you need to memorize a table for all sequential data structures(Queue, Deque, LinkedList), + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OperationJava ArrayListJava QueueJava ArrayDequeJava LinkedList
pushaddofferpushpush
popremovepollremoveLastremoveLast
shiftremovepollremoveFirstremoveFirst
unshiftadd(0, element)offerFirstunshiftunshift
+ +whereas in our data-structure-typed, you **only** need to remember four methods: `push`, `pop`, `shift`, and `unshift` for all sequential data structures. + ## Installation and Usage ### npm @@ -155,7 +204,7 @@ our [visual tool](https://github.com/zrwusa/vivid-algorithm) #### TS ```ts -import {RedBlackTree} from 'data-structure-typed'; +import { RedBlackTree } from 'data-structure-typed'; const rbTree = new RedBlackTree(); rbTree.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]) @@ -177,7 +226,7 @@ rbTree.print() #### JS ```js -import {RedBlackTree} from 'data-structure-typed'; +import { RedBlackTree } from 'data-structure-typed'; const rbTree = new RedBlackTree(); rbTree.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]) @@ -204,31 +253,31 @@ const orgStrArr = ["trie", "trial", "trick", "trip", "tree", "trend", "triangle" const entries = [[6, "6"], [1, "1"], [2, "2"], [7, "7"], [5, "5"], [3, "3"], [4, "4"], [9, "9"], [8, "8"]]; const queue = new Queue(orgArr); -queue.print(); +queue.print(); // [6, 1, 2, 7, 5, 3, 4, 9, 8] const deque = new Deque(orgArr); -deque.print(); +deque.print(); // [6, 1, 2, 7, 5, 3, 4, 9, 8] const sList = new SinglyLinkedList(orgArr); -sList.print(); +sList.print(); // [6, 1, 2, 7, 5, 3, 4, 9, 8] const dList = new DoublyLinkedList(orgArr); -dList.print(); +dList.print(); // [6, 1, 2, 7, 5, 3, 4, 9, 8] const stack = new Stack(orgArr); -stack.print(); +stack.print(); // [6, 1, 2, 7, 5, 3, 4, 9, 8] const minHeap = new MinHeap(orgArr); -minHeap.print(); +minHeap.print(); // [1, 5, 2, 7, 6, 3, 4, 9, 8] const maxPQ = new MaxPriorityQueue(orgArr); -maxPQ.print(); +maxPQ.print(); // [9, 8, 4, 7, 5, 2, 3, 1, 6] const biTree = new BinaryTree(entries); @@ -284,7 +333,7 @@ treeMulti.print(); // 7 9 const hm = new HashMap(entries); -hm.print() +hm.print() // [[6, "6"], [1, "1"], [2, "2"], [7, "7"], [5, "5"], [3, "3"], [4, "4"], [9, "9"], [8, "8"]] const rbTreeH = new RedBlackTree(hm); @@ -298,7 +347,7 @@ rbTreeH.print(); // 7 9 const pq = new MinPriorityQueue(orgArr); -pq.print(); +pq.print(); // [1, 5, 2, 7, 6, 3, 4, 9, 8] const bst1 = new BST(pq); @@ -312,7 +361,7 @@ bst1.print(); // 4 9 const dq1 = new Deque(orgArr); -dq1.print(); +dq1.print(); // [6, 1, 2, 7, 5, 3, 4, 9, 8] const rbTree1 = new RedBlackTree(dq1); rbTree1.print(); @@ -326,13 +375,13 @@ rbTree1.print(); const trie2 = new Trie(orgStrArr); -trie2.print(); +trie2.print(); // ['trie', 'trial', 'triangle', 'trick', 'trip', 'tree', 'trend', 'track', 'trace', 'transmit'] const heap2 = new Heap(trie2, { comparator: (a, b) => Number(a) - Number(b) }); -heap2.print(); +heap2.print(); // ['transmit', 'trace', 'tree', 'trend', 'track', 'trial', 'trip', 'trie', 'trick', 'triangle'] const dq2 = new Deque(heap2); -dq2.print(); +dq2.print(); // ['transmit', 'trace', 'tree', 'trend', 'track', 'trial', 'trip', 'trie', 'trick', 'triangle'] const entries2 = dq2.map((el, i) => [i, el]); const avl2 = new AVLTree(entries2); @@ -349,7 +398,7 @@ avl2.print(); ### Binary Search Tree (BST) snippet ```ts -import {BST, BSTNode} from 'data-structure-typed'; +import { BST, BSTNode } from 'data-structure-typed'; const bst = new BST(); bst.add(11); @@ -381,7 +430,7 @@ bst.print() // \ // 7 -const objBST = new BST(); +const objBST = new BST(); objBST.add(11, { "name": "Pablo", "age": 15 }); objBST.add(3, { "name": "Kirk", "age": 1 }); @@ -410,7 +459,7 @@ objBST.delete(11); ### AVLTree snippet ```ts -import {AVLTree} from 'data-structure-typed'; +import { AVLTree } from 'data-structure-typed'; const avlTree = new AVLTree(); avlTree.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]) @@ -422,7 +471,7 @@ avlTree.isAVLBalanced(); // true ### Directed Graph simple snippet ```ts -import {DirectedGraph} from 'data-structure-typed'; +import { DirectedGraph } from 'data-structure-typed'; const graph = new DirectedGraph(); @@ -451,7 +500,7 @@ const topologicalOrderKeys = graph.topologicalSort(); // ['A', 'B', 'C'] ### Undirected Graph snippet ```ts -import {UndirectedGraph} from 'data-structure-typed'; +import { UndirectedGraph } from 'data-structure-typed'; const graph = new UndirectedGraph(); graph.addVertex('A'); @@ -885,7 +934,10 @@ Array.from(dijkstraResult?.seen ?? []).map(vertex => vertex.key) // ['A', 'B', ' ## Software Engineering Design Standards -We strictly adhere to computer science theory and software development standards. Our LinkedList is designed in the traditional sense of the LinkedList data structure, and we refrain from substituting it with a Deque solely for the purpose of showcasing performance test data. However, we have also implemented a Deque based on a dynamic array concurrently. +We strictly adhere to computer science theory and software development standards. Our LinkedList is designed in the +traditional sense of the LinkedList data structure, and we refrain from substituting it with a Deque solely for the +purpose of showcasing performance test data. However, we have also implemented a Deque based on a dynamic array +concurrently. @@ -935,7 +987,6 @@ We strictly adhere to computer science theory and software development standards
- ## Benchmark [//]: # (No deletion!!! Start of Replace Section) @@ -982,9 +1033,8 @@ We strictly adhere to computer science theory and software development standards [//]: # (No deletion!!! End of Replace Section) - - ## supported module system + Now you can use it in Node.js and browser environments CommonJS:**`require export.modules =`** @@ -1002,19 +1052,21 @@ Copy the line below into the head tag in an HTML document. #### development ```html + ``` #### production ```html + ``` Copy the code below into the script tag of your HTML, and you're good to go with your development. ```js -const {Heap} = dataStructureTyped; +const { Heap } = dataStructureTyped; const { BinaryTree, Graph, Queue, Stack, PriorityQueue, BST, Trie, DoublyLinkedList, AVLTree, MinHeap, SinglyLinkedList, DirectedGraph, TreeMultiMap, diff --git a/SPECIFICATION.md b/SPECIFICATION.md index 539193e..c928323 100644 --- a/SPECIFICATION.md +++ b/SPECIFICATION.md @@ -45,7 +45,7 @@ ### Use of Commonly Understood Industry Standard Naming -- `enqueue`, `dequeue`, `push`, `pop`, `poll`, `addLast`, `addFirst`, `pollFirst`, `pollLast`, `isEmpty`, `clear`, `print`, `clone`. +- `enqueue`, `dequeue`, `push`, `pop`, `poll`, `push`, `unshift`, `shift`, `pop`, `isEmpty`, `clear`, `print`, `clone`. ### Implementation of Customizable Features Whenever Possible @@ -53,4 +53,4 @@ ### Comprehensive Documentation -- The documentation not only explains the purpose of methods but also annotates time and space complexity across the entire series. +- The documentation not only explains the purpose of methods but also annotates time and space complexity across the entire series. \ No newline at end of file diff --git a/SPECIFICATION_zh-CN.md b/SPECIFICATION_zh-CN.md new file mode 100644 index 0000000..b09b1b5 --- /dev/null +++ b/SPECIFICATION_zh-CN.md @@ -0,0 +1,81 @@ + +[NPM](https://www.npmjs.com/package/data-structure-typed) + +[Github](https://github.com/zrwusa/data-structure-typed) + +## Pain Points Addressed + +### Enhancing the Performance of Simulated Data Structures in JS/TS + +- `Queue`: While many resort to using Arrays to simulate Queues and Deques, the time complexity of Array.shift is O(n). We have tackled this challenge by implementing a Queue and Deque with O(1) time complexity for enqueue and dequeue operations. + +- `HashMap`: Opting for a pure HashMap over the built-in Map (technically a LinkedHashMap) can boost algorithmic speed. However, the performance is compromised due to the necessity of considering insertion order. We have independently implemented an optimized HashMap. + +- `Stack`: In JS, simulating a Stack with an Array is acceptable, and its performance is on par with a genuine Stack. + +### Introducing Missing Native Data Structures in JS/TS + +- `Heap / Priority Queue`: Algorithms with O(log n) time complexity have been pivotal in improving efficiency since the dawn of computers. A Heap supports insertion, deletion, and search with O(log n) time complexity, coupled with the ability to obtain the minimum / maximum value in O(1) time. + +- `Red Black Tree`: Developers well-versed in databases, file systems, Linux virtual memory management, and network routing tables often have a nuanced understanding of Red-Black Trees. It stands out as the least operation-intensive among all balanced binary search trees, offering optimal performance balance in CRUD operations. + +- `Linked List`: In scenarios where insertion or deletion of elements with O(1) time complexity is required at a specific index in an ordered collection, JS lacks a provided data structure. Hence, the need for a LinkedList to implement this functionality. + +- `Trie`: Efficient for fast string queries and space-efficient string storage, yet not commonly found in the standard libraries of most programming languages. + +- `Graph`: This data structure is not commonly found in the standard libraries of most languages, making it a non-issue in JS. + +## Advantages + +### Performance: + +- The performance of some ours data structures has surpassed JS's built-in data structures (`Queue`, `Deque`, `HashMap`), while most are comparable to or even surpass those in other languages. Some are still undergoing refinement (`Graph`, `AVL Tree`). + +### Uniformity + +- 1. Implementation or constraint of `forEach`, `filter`, `map`, `every`, `some`, `reduce`, `find`, `has`, `hasValue`, `get`, `print`, `isEmpty`, `clear`, `clone` methods in the base class. +- 2. Use of generators to uniformly implement `[Symbol.iterator]`, `entries`, `keys`, `values`. Delaying iterator execution prevents performance loss and provides control during traversal. +- 3. All deletion methods uniformly use the widely adopted `delete` in ES6, while addition methods uniformly use `add`. Compatibility with some specifications in Java. +- 4. The first parameter for all constructors is data, and the second parameter is configuration, maintaining uniformity. The first parameter accepts any iterable type for seamless conversion between data structures. +- 5. Uniform return types, for example, the `add` method consistently returns a boolean. + +### Convenience and Simplicity of APIs + +- Inspired by ES6, Java, ESNext, TypeScript, Python, featuring methods like `forEach`, `filter`, `map`, `every`, `some`, `reduce`, `find`, `has`, `hasValue` and `get`. + +### Use of Commonly Understood Industry Standard Naming + +- `enqueue`, `dequeue`, `push`, `pop`, `poll`, `push`, `unshift`, `shift`, `pop`, `isEmpty`, `clear`, `print`, `clone`. + +### Implementation of Customizable Features Whenever Possible + +- Such as providing callback functions (lambda expressions) for all traversal methods. + +### Comprehensive Documentation + +- The documentation not only explains the purpose of methods but also annotates time and space complexity across the entire series. + +像getter和setter是优于Java的getXxx和setXxx + +Java中 +添加元素(类似 push): +add(E element): 将元素添加到列表的末尾。 +add(int index, E element): 在指定的索引位置插入元素。 + +移除元素(类似 pop): +remove(int index): 移除指定索引位置的元素。 + +获取并移除首个元素(类似 shift): +remove(0): 移除索引为0的元素。 + +在首位插入元素(类似 unshift): +add(0, E element): 在指定索引(0)处插入元素。 + + +大多数程序员更喜欢JS中的Array的push, pop, shift, unshift。 + +原因有以下几点: + +命名更直观。JS中的push, pop, shift, unshift的命名更加直观,可以直接理解其操作的含义。而Java中的add和remove的命名则比较抽象,需要一定的理解才能理解其操作的含义。 +使用更方便。JS中的push, pop, shift, unshift的操作更加方便,只需要一个参数即可完成操作。而Java中的add和remove的操作则需要两个参数,第一个参数指定操作的索引,第二个参数指定操作的值。 +性能更高。JS中的push, pop, shift, unshift的性能更高,因为其操作只需要修改数组的长度即可完成。而Java中的add和remove的性能则较低,因为其操作需要移动数组中的元素。 \ No newline at end of file diff --git a/SPONSOR-zh-CN.md b/SPONSOR_zh-CN.md similarity index 97% rename from SPONSOR-zh-CN.md rename to SPONSOR_zh-CN.md index 5fbf74c..56d4f6a 100644 --- a/SPONSOR-zh-CN.md +++ b/SPONSOR_zh-CN.md @@ -68,7 +68,7 @@ ### 使用通俗易懂业界常用命名 -- `enqueue`, `dequeue`, `push`, `pop`, `poll`, `addLast`, `addFirst`, `pollFirst`, `pollLast`, `isEmpty`, `clear`, `print`, `clone` +- `enqueue`, `dequeue`, `push`, `pop`, `poll`, `push`, `unshift`, `shift`, `pop`, `isEmpty`, `clear`, `print`, `clone` ### 尽量实现可定制化功能 diff --git a/src/data-structures/linked-list/doubly-linked-list.ts b/src/data-structures/linked-list/doubly-linked-list.ts index ad7935d..4a29580 100644 --- a/src/data-structures/linked-list/doubly-linked-list.ts +++ b/src/data-structures/linked-list/doubly-linked-list.ts @@ -194,14 +194,13 @@ export class DoublyLinkedList extends IterableElementBase { */ /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The push function adds a new node with the given value to the end of the doubly linked list. - * @param {E} value - The value to be added to the linked list. + * The push function adds a new element to the end of a doubly linked list. + * @param {E} element - The "element" parameter represents the value that you want to add to the + * doubly linked list. + * @returns The `push` method is returning a boolean value, `true`. */ - push(value: E): boolean { - const newNode = new DoublyLinkedListNode(value); + push(element: E): boolean { + const newNode = new DoublyLinkedListNode(element); if (!this.head) { this._head = newNode; this._tail = newNode; @@ -220,12 +219,8 @@ export class DoublyLinkedList extends IterableElementBase { */ /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The `pop()` function removes and returns the value of the last node in a doubly linked list. - * @returns The method is returning the value of the removed node (removedNode.value) if the list is not empty. If the - * list is empty, it returns undefined. + * The `pop()` function removes and returns the value of the last element in a linked list. + * @returns The method is returning the value of the removed node. */ pop(): E | undefined { if (!this.tail) return undefined; @@ -247,12 +242,8 @@ export class DoublyLinkedList extends IterableElementBase { */ /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The `shift()` function removes and returns the value of the first node in a doubly linked list. - * @returns The method `shift()` returns the value of the node that is removed from the beginning of the doubly linked - * list. + * The `shift()` function removes and returns the value of the first element in a doubly linked list. + * @returns The value of the removed node. */ shift(): E | undefined { if (!this.head) return undefined; @@ -274,15 +265,13 @@ export class DoublyLinkedList extends IterableElementBase { */ /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The unshift function adds a new node with the given value to the beginning of a doubly linked list. - * @param {E} value - The `value` parameter represents the value of the new node that will be added to the beginning of the - * doubly linked list. + * The unshift function adds a new element to the beginning of a doubly linked list. + * @param {E} element - The "element" parameter represents the value of the element that you want to + * add to the beginning of the doubly linked list. + * @returns The `unshift` method is returning a boolean value, `true`. */ - unshift(value: E): boolean { - const newNode = new DoublyLinkedListNode(value); + unshift(element: E): boolean { + const newNode = new DoublyLinkedListNode(element); if (!this.head) { this._head = newNode; this._tail = newNode; @@ -811,73 +800,6 @@ export class DoublyLinkedList extends IterableElementBase { return mappedList; } - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The addLast function adds a new node with the given value to the end of the doubly linked list. - * @param {E} value - The value to be added to the linked list. - */ - addLast(value: E): boolean { - return this.push(value); - } - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The `pollLast()` function removes and returns the value of the last node in a doubly linked list. - * @returns The method is returning the value of the removed node (removedNode.value) if the list is not empty. If the - * list is empty, it returns undefined. - */ - pollLast(): E | undefined { - return this.pop(); - } - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The `pollFirst()` function removes and returns the value of the first node in a doubly linked list. - * @returns The method `shift()` returns the value of the node that is removed from the beginning of the doubly linked - * list. - */ - pollFirst(): E | undefined { - return this.shift(); - } - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The addFirst function adds a new node with the given value to the beginning of a doubly linked list. - * @param {E} value - The `value` parameter represents the value of the new node that will be added to the beginning of the - * doubly linked list. - */ - addFirst(value: E): void { - this.unshift(value); - } - /** * The function returns an iterator that iterates over the values of a linked list. */ diff --git a/src/data-structures/linked-list/singly-linked-list.ts b/src/data-structures/linked-list/singly-linked-list.ts index 00a2531..65cafb3 100644 --- a/src/data-structures/linked-list/singly-linked-list.ts +++ b/src/data-structures/linked-list/singly-linked-list.ts @@ -93,6 +93,24 @@ export class SinglyLinkedList extends IterableElementBase { 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 _size: number = 0; /** @@ -130,20 +148,19 @@ export class SinglyLinkedList extends IterableElementBase { /** * Time Complexity: O(1) * Space Complexity: O(1) - * Constant time, as it involves basic pointer adjustments. - * Constant space, as it only creates a new node. */ /** * Time Complexity: O(1) * Space Complexity: O(1) * - * The `push` function adds a new node with the given value to the end of a singly linked list. - * @param {E} value - The "value" parameter represents the value that you want to add to the linked list. It can be of - * any type (E) as specified in the generic type declaration of the class or function. + * 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`. */ - push(value: E): boolean { - const newNode = new SinglyLinkedListNode(value); + push(element: E): boolean { + const newNode = new SinglyLinkedListNode(element); if (!this.head) { this._head = newNode; this._tail = newNode; @@ -155,23 +172,6 @@ export class SinglyLinkedList extends IterableElementBase { return true; } - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The `push` function adds a new node with the given value to the end of a singly linked list. - * @param {E} value - The "value" parameter represents the value that you want to add to the linked list. It can be of - * any type (E) as specified in the generic type declaration of the class or function. - */ - addLast(value: E): boolean { - return this.push(value); - } - /** * Time Complexity: O(n) * Space Complexity: O(1) @@ -182,10 +182,9 @@ export class SinglyLinkedList extends IterableElementBase { * Time Complexity: O(n) * Space Complexity: O(1) * - * The `pop()` function removes and returns the value of the last element in a linked list, updating the head and tail - * pointers accordingly. - * @returns The method `pop()` returns the value of the node that is being removed from the end of the linked list. If - * the linked list is empty, it returns `undefined`. + * The `pop` function removes and returns the value of the last element in a linked list. + * @returns The method is returning the value of the element that is being popped from the end of the + * list. */ pop(): E | undefined { if (!this.head) return undefined; @@ -208,24 +207,6 @@ export class SinglyLinkedList extends IterableElementBase { return value; } - /** - * Time Complexity: O(n) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(n) - * Space Complexity: O(1) - * - * The `pollLast()` function removes and returns the value of the last element in a linked list, updating the head and tail - * pointers accordingly. - * @returns The method `pop()` returns the value of the node that is being removed from the end of the linked list. If - * the linked list is empty, it returns `undefined`. - */ - pollLast(): E | undefined { - return this.pop(); - } - /** * Time Complexity: O(1) * Space Complexity: O(1) @@ -235,8 +216,8 @@ export class SinglyLinkedList extends IterableElementBase { * Time Complexity: O(1) * Space Complexity: O(1) * - * The `shift()` function removes and returns the value of the first node in a linked list. - * @returns The value of the node that is being removed from the beginning of the linked list. + * The `shift()` function removes and returns the value of the first element in a linked list. + * @returns The value of the removed node. */ shift(): E | undefined { if (!this.head) return undefined; @@ -255,28 +236,13 @@ export class SinglyLinkedList extends IterableElementBase { * Time Complexity: O(1) * Space Complexity: O(1) * - * The `pollFirst()` function removes and returns the value of the first node in a linked list. - * @returns The value of the node that is being removed from the beginning of the linked list. + * 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`. */ - pollFirst(): E | undefined { - return this.shift(); - } - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The unshift function adds a new node with the given value to the beginning of a singly linked list. - * @param {E} value - The parameter "value" represents the value of the new node that will be added to the beginning of the - * linked list. - */ - unshift(value: E): boolean { - const newNode = new SinglyLinkedListNode(value); + unshift(element: E): boolean { + const newNode = new SinglyLinkedListNode(element); if (!this.head) { this._head = newNode; this._tail = newNode; @@ -288,27 +254,9 @@ export class SinglyLinkedList extends IterableElementBase { return true; } - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The addFirst function adds a new node with the given value to the beginning of a singly linked list. - * @param {E} value - The parameter "value" represents the value of the new node that will be added to the beginning of the - * linked list. - */ - addFirst(value: E): boolean { - return this.unshift(value); - } - /** * Time Complexity: O(n) * Space Complexity: O(1) - * Linear time, where n is the index, as it may need to traverse the list to find the desired node. */ /** diff --git a/src/data-structures/queue/deque.ts b/src/data-structures/queue/deque.ts index 525e36b..f1a80ce 100644 --- a/src/data-structures/queue/deque.ts +++ b/src/data-structures/queue/deque.ts @@ -811,73 +811,6 @@ export class Deque extends IterableElementBase { return newDeque; } - /** - * Time Complexity: Amortized O(1) - Similar to push, resizing leads to O(n). - * Space Complexity: O(n) - Due to potential resizing. - */ - - /** - * Time Complexity: Amortized O(1) - Similar to push, resizing leads to O(n). - * Space Complexity: O(n) - Due to potential resizing. - * - * The addLast function adds an element to the end of an array. - * @param {E} element - The element parameter represents the element that you want to add to the end of the - * data structure. - */ - addLast(element: E): boolean { - return this.push(element); - } - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The function "pollLast" removes and returns the last element of an array. - * @returns The last element of the array is being returned. - */ - pollLast(): E | undefined { - return this.pop(); - } - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * / - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The "addFirst" function adds an element to the beginning of an array. - * @param {E} element - The parameter "element" represents the element that you want to add to the - * beginning of the data structure. - */ - addFirst(element: E): boolean { - return this.unshift(element); - } - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * / - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The function "pollFirst" removes and returns the first element of an array. - * @returns The method `pollFirst()` is returning the first element of the array after removing it - * from the beginning. If the array is empty, it will return `undefined`. - */ - pollFirst(): E | undefined { - return this.shift(); - } - /** * Time Complexity: O(n) * Space Complexity: O(1) diff --git a/src/data-structures/queue/queue.ts b/src/data-structures/queue/queue.ts index 32192a0..cbeed65 100644 --- a/src/data-structures/queue/queue.ts +++ b/src/data-structures/queue/queue.ts @@ -178,72 +178,6 @@ export class Queue extends IterableElementBase { return spliced.length === 1; } - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The `peek` function returns the first element of the array `_elements` if it exists, otherwise it returns `undefined`. - * @returns The `peek()` method returns the first element of the data structure, represented by the `_elements` array at - * the `_offset` index. If the data structure is empty (size is 0), it returns `undefined`. - */ - peek(): E | undefined { - return this.first; - } - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The `peekLast` function returns the last element in an array-like data structure, or undefined if the structure is empty. - * @returns The method `peekLast()` returns the last element of the `_elements` array if the array is not empty. If the - * array is empty, it returns `undefined`. - */ - peekLast(): E | undefined { - return this.last; - } - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The enqueue function adds a value to the end of a queue. - * @param {E} value - The value parameter represents the value that you want to add to the queue. - */ - enqueue(value: E): boolean { - return this.push(value); - } - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The `dequeue` function removes and returns the first element from a queue, or returns undefined if the queue is empty. - * @returns The method is returning a value of type E or undefined. - */ - dequeue(): E | undefined { - return this.shift(); - } - /** * Time Complexity: O(1) * Space Complexity: O(1) @@ -411,38 +345,6 @@ export class Queue extends IterableElementBase { * 4. Frequent Enqueuing and Dequeuing Operations: If your application involves frequent enqueuing and dequeuing operations and is less concerned with random access, then LinkedListQueue is a good choice. */ export class LinkedListQueue extends SinglyLinkedList { - /** - * The `get first` function returns the value of the head node in a linked list, or `undefined` if the list is empty. - * @returns The `get first()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`. - */ - get first(): E | undefined { - return this.head?.value; - } - - /** - * The enqueue function adds a value to the end of an array. - * @param {E} value - The value parameter represents the value that you want to add to the queue. - */ - enqueue(value: E): boolean { - return this.push(value); - } - - /** - * The `dequeue` function removes and returns the first element from a queue, or returns undefined if the queue is empty. - * @returns The method is returning the element at the front of the queue, or undefined if the queue is empty. - */ - dequeue(): E | undefined { - return this.shift(); - } - - /** - * The `peek` function returns the value of the head node in a linked list, or `undefined` if the list is empty. - * @returns The `peek()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`. - */ - peek(): E | undefined { - return this.first; - } - /** * Time Complexity: O(n) * Space Complexity: O(n) diff --git a/test/unit/data-structures/linked-list/doubly-linked-list.test.ts b/test/unit/data-structures/linked-list/doubly-linked-list.test.ts index 584cecf..b2e55e3 100644 --- a/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +++ b/test/unit/data-structures/linked-list/doubly-linked-list.test.ts @@ -39,12 +39,12 @@ describe('DoublyLinkedList Operation Test', () => { it('should clone', function () { const dList = new DoublyLinkedList(); - dList.addLast('1'); - dList.addLast('6'); - dList.addLast('2'); - dList.addLast('0'); - dList.addLast('5'); - dList.addLast('9'); + dList.push('1'); + dList.push('6'); + dList.push('2'); + dList.push('0'); + dList.push('5'); + dList.push('9'); dList.delete('2'); expect([...dList]).toEqual(['1', '6', '0', '5', '9']); const cloned = dList.clone(); diff --git a/test/unit/data-structures/linked-list/singly-linked-list.test.ts b/test/unit/data-structures/linked-list/singly-linked-list.test.ts index c8743a3..23b4329 100644 --- a/test/unit/data-structures/linked-list/singly-linked-list.test.ts +++ b/test/unit/data-structures/linked-list/singly-linked-list.test.ts @@ -32,7 +32,7 @@ describe('SinglyLinkedList Operation Test', () => { list.push(3); const popped = list.pop(); expect(popped).toBe(3); - expect(list.pollLast()).toBe(2); + expect(list.pop()).toBe(2); expect(list.toArray()).toEqual([1]); }); @@ -49,7 +49,7 @@ describe('SinglyLinkedList Operation Test', () => { list.push(3); const shifted = list.shift(); expect(shifted).toBe(1); - expect(list.pollFirst()).toBe(2); + expect(list.shift()).toBe(2); expect(list.toArray()).toEqual([3]); }); @@ -62,7 +62,7 @@ describe('SinglyLinkedList Operation Test', () => { describe('unshift', () => { it('should add elements to the beginning of the list', () => { list.unshift(1); - list.addFirst(2); + list.unshift(2); expect(list.toArray()).toEqual([2, 1]); }); }); @@ -350,12 +350,12 @@ describe('SinglyLinkedList Operation Test', () => { it('should clone', function () { const sList = new SinglyLinkedList(); - sList.addLast('1'); - sList.addLast('6'); - sList.addLast('2'); - sList.addLast('0'); - sList.addLast('5'); - sList.addLast('9'); + sList.push('1'); + sList.push('6'); + sList.push('2'); + sList.push('0'); + sList.push('5'); + sList.push('9'); sList.delete('2'); expect([...sList]).toEqual(['1', '6', '0', '5', '9']); const cloned = sList.clone(); @@ -478,7 +478,7 @@ describe('SinglyLinkedList', () => { }); it('should map the list', () => { - list.addLast(1); + list.push(1); list.push(2); list.push(3); expect(list.map(value => value * 2).toArray()).toEqual([2, 4, 6]); diff --git a/test/unit/data-structures/linked-list/skip-list.test.ts b/test/unit/data-structures/linked-list/skip-list.test.ts index c8c9d34..a1d9183 100644 --- a/test/unit/data-structures/linked-list/skip-list.test.ts +++ b/test/unit/data-structures/linked-list/skip-list.test.ts @@ -65,21 +65,21 @@ describe('SkipList Test2', () => { skipList.add(4, 'Four'); }); - it('getFirst() should return the getFirst element', () => { + it('first() should return the first element', () => { expect(skipList.first).toBe('One'); }); - it('getLast() should return the getLast element', () => { + it('last() should return the last element', () => { expect(skipList.last).toBe('Four'); }); - it('higher(key) should return the getFirst element greater than the given key', () => { + it('higher(key) should return the first element greater than the given key', () => { expect(skipList.higher(2)).toBe('Three'); expect(skipList.higher(3)).toBe('Four'); expect(skipList.higher(4)).toBeUndefined(); }); - it('lower(key) should return the getLast element less than the given key', () => { + it('lower(key) should return the last element less than the given key', () => { expect(skipList.lower(2)).toBe('One'); expect(skipList.lower(1)).toBe(undefined); }); diff --git a/test/unit/data-structures/queue/deque.test.ts b/test/unit/data-structures/queue/deque.test.ts index b512b0f..5279846 100644 --- a/test/unit/data-structures/queue/deque.test.ts +++ b/test/unit/data-structures/queue/deque.test.ts @@ -52,12 +52,12 @@ describe('Deque - Basic Operations', () => { it('should clone', function () { const deque = new Deque(); - deque.addLast('1'); - deque.addLast('6'); - deque.addLast('2'); - deque.addLast('0'); - deque.addLast('5'); - deque.addLast('9'); + deque.push('1'); + deque.push('6'); + deque.push('2'); + deque.push('0'); + deque.push('5'); + deque.push('9'); expect(deque.size).toBe(6); deque.delete('2'); expect(deque.size).toBe(5); @@ -70,7 +70,7 @@ describe('Deque - Basic Operations', () => { expect([...deque]).toEqual(['1', '6', '0', '9']); expect([...cloned]).toEqual(['1', '6', '0', '5', '9']); expect(cloned.size).toBe(5); - cloned.addLast('8'); + cloned.push('8'); expect(cloned.size).toBe(6); cloned.delete('6'); expect(cloned.size).toBe(5); @@ -239,52 +239,52 @@ describe('Deque - Additional Operations', () => { deque = new Deque(); }); - test('addLast should add an element to the end', () => { - deque.addLast(1); - deque.addLast(2); + test('push should add an element to the end', () => { + deque.push(1); + deque.push(2); expect(deque.last).toBe(2); expect(deque.size).toBe(2); }); - test('pollLast should remove and return the last element', () => { - deque.addLast(1); - deque.addLast(2); - expect(deque.pollLast()).toBe(2); + test('pop should remove and return the last element', () => { + deque.push(1); + deque.push(2); + expect(deque.pop()).toBe(2); expect(deque.size).toBe(1); }); - test('addFirst should add an element to the beginning', () => { - deque.addFirst(1); - deque.addFirst(2); + test('unshift should add an element to the beginning', () => { + deque.unshift(1); + deque.unshift(2); expect(deque.first).toBe(2); expect(deque.size).toBe(2); }); - test('pollFirst should remove and return the first element', () => { - deque.addFirst(1); - deque.addFirst(2); - expect(deque.pollFirst()).toBe(2); + test('shift should remove and return the first element', () => { + deque.unshift(1); + deque.unshift(2); + expect(deque.shift()).toBe(2); expect(deque.size).toBe(1); }); test('clear should reset the deque', () => { - deque.addFirst(1); + deque.unshift(1); deque.clear(); expect(deque.size).toBe(0); expect(deque.isEmpty()).toBeTruthy(); }); test('begin should yield elements from the beginning', () => { - deque.addLast(1); - deque.addLast(2); + deque.push(1); + deque.push(2); const iterator = deque.begin(); expect(iterator.next().value).toBe(1); expect(iterator.next().value).toBe(2); }); test('reverseBegin should yield elements in reverse order', () => { - deque.addLast(1); - deque.addLast(2); + deque.push(1); + deque.push(2); const iterator = deque.reverseBegin(); expect(iterator.next().value).toBe(2); expect(iterator.next().value).toBe(1); diff --git a/test/unit/data-structures/queue/queue.test.ts b/test/unit/data-structures/queue/queue.test.ts index 7dcff62..5d89eb5 100644 --- a/test/unit/data-structures/queue/queue.test.ts +++ b/test/unit/data-structures/queue/queue.test.ts @@ -23,24 +23,24 @@ describe('Queue', () => { test('shift should remove the first element', () => { queue.push(1); - queue.enqueue(2); + queue.push(2); expect(queue.shift()).toBe(1); expect(queue.size).toBe(1); }); test('shift should return undefined if queue is empty', () => { - expect(queue.dequeue()).toBeUndefined(); + expect(queue.shift()).toBeUndefined(); }); - test('peek should return the first element without removing it', () => { + test('first should return the first element without removing it', () => { queue.push(1); queue.push(2); - expect(queue.peek()).toBe(1); + expect(queue.first).toBe(1); expect(queue.size).toBe(2); }); - test('peek should return undefined if queue is empty', () => { - expect(queue.peek()).toBeUndefined(); + test('first should return undefined if queue is empty', () => { + expect(queue.first).toBeUndefined(); }); test('size should return the number of elements', () => { @@ -167,12 +167,12 @@ describe('Queue - Additional Methods', () => { test('peekLast should return the last element without removing it', () => { queue.push(1); queue.push(2); - expect(queue.peekLast()).toBe(2); + expect(queue.last).toBe(2); expect(queue.size).toBe(2); }); test('peekLast should return undefined if queue is empty', () => { - expect(queue.peekLast()).toBeUndefined(); + expect(queue.last).toBeUndefined(); }); test('at should return the element at the specified index', () => { @@ -239,25 +239,25 @@ describe('LinkedListQueue', () => { queue = new LinkedListQueue(); }); - it('should enqueue elements to the end of the queue', () => { - queue.enqueue('A'); - queue.enqueue('B'); - expect(queue.peek()).toBe('A'); + it('should push elements to the end of the queue', () => { + queue.push('A'); + queue.push('B'); + expect(queue.first).toBe('A'); expect(queue.size).toBe(2); }); - it('should dequeue elements from the front of the queue', () => { - queue.enqueue('A'); - queue.enqueue('B'); - const dequeued = queue.dequeue(); + it('should shift elements from the front of the queue', () => { + queue.push('A'); + queue.push('B'); + const dequeued = queue.shift(); expect(dequeued).toBe('A'); - expect(queue.peek()).toBe('B'); + expect(queue.first).toBe('B'); expect(queue.size).toBe(1); }); it('should peek at the front of the queue', () => { - queue.enqueue('A'); - queue.enqueue('B'); - expect(queue.peek()).toBe('A'); + queue.push('A'); + queue.push('B'); + expect(queue.first).toBe('A'); }); });