typescript-ds-lib 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typescript-ds-lib",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "A collection of TypeScript data structure implementations",
5
5
  "author": "Artiom Baloian <artiom.baloian@gmail.com>",
6
6
  "license": "MIT",
@@ -8,14 +8,12 @@
8
8
  "types": "dist/index.d.ts",
9
9
  "files": [
10
10
  "dist",
11
- "lib",
12
- "types",
13
11
  "README.md",
14
12
  "LICENSE"
15
13
  ],
16
14
  "scripts": {
17
15
  "build": "rm -rf dist && tsc",
18
- "prepare": "npm run build",
16
+ "prepare": "npm run build",
19
17
  "test": "rm -rf dist && tsc && jest"
20
18
  },
21
19
  "repository": {
@@ -1,218 +0,0 @@
1
- import { Comparator } from '../types';
2
-
3
-
4
- export interface BinarySearchTree<T> {
5
- insert(element: T): void;
6
- remove(element: T): void;
7
- find(element: T): boolean;
8
- min(): T | undefined;
9
- max(): T | undefined;
10
- forEach(callback: (element: T) => void, traversal?: 'inorder' | 'preorder' | 'postorder'): void;
11
- isEmpty(): boolean;
12
- clear(): void;
13
- count(): number;
14
- }
15
-
16
-
17
- class TreeNode<T> {
18
- value: T;
19
- left: TreeNode<T> | null;
20
- right: TreeNode<T> | null;
21
-
22
- constructor(value: T) {
23
- this.value = value;
24
- this.left = null;
25
- this.right = null;
26
- }
27
- }
28
-
29
-
30
- export class BinarySearchTree<T> implements BinarySearchTree<T> {
31
- private root: TreeNode<T> | null;
32
- private comparator: Comparator<T>;
33
-
34
- constructor(comparator: Comparator<T> = (a: T, b: T) => a < b) {
35
- this.root = null;
36
- this.comparator = comparator;
37
- }
38
-
39
- /**
40
- * Inserts a value into the BST
41
- */
42
- insert(value: T): void {
43
- const newNode = new TreeNode(value);
44
- if (!this.root) {
45
- this.root = newNode;
46
- return;
47
- }
48
- let current = this.root;
49
- while (true) {
50
- if (this.comparator(value, current.value)) {
51
- if (current.left === null) {
52
- current.left = newNode;
53
- break;
54
- }
55
- current = current.left;
56
- } else {
57
- if (current.right === null) {
58
- current.right = newNode;
59
- break;
60
- }
61
- current = current.right;
62
- }
63
- }
64
- }
65
-
66
- /**
67
- * Searches for a value in the BST. Returns true if found, false otherwise
68
- */
69
- find(value: T): boolean {
70
- let current = this.root;
71
- while (current !== null) {
72
- if (this.isEqual(value, current.value)) {
73
- return true;
74
- }
75
- if (this.comparator(value, current.value)) {
76
- current = current.left;
77
- } else {
78
- current = current.right;
79
- }
80
- }
81
- return false;
82
- }
83
-
84
- /**
85
- * Returns the minimum value in the BST, or undefined if tree is empty
86
- */
87
- min(): T | undefined {
88
- if (!this.root) return undefined;
89
- let current = this.root;
90
- while (current.left !== null) {
91
- current = current.left;
92
- }
93
- return current.value;
94
- }
95
-
96
- /**
97
- * Returns the maximum value in the BST, or undefined if tree is empty
98
- */
99
- max(): T | undefined {
100
- if (!this.root) return undefined;
101
- let current = this.root;
102
- while (current.right !== null) {
103
- current = current.right;
104
- }
105
- return current.value;
106
- }
107
-
108
- /**
109
- * Removes a value from the BST if it exists
110
- */
111
- remove(value: T): void {
112
- this.root = this.removeNode(this.root, value);
113
- }
114
-
115
- private removeNode(node: TreeNode<T> | null, value: T): TreeNode<T> | null {
116
- if (node === null) return null;
117
- if (this.comparator(value, node.value)) {
118
- node.left = this.removeNode(node.left, value);
119
- return node;
120
- } else if (this.comparator(node.value, value)) {
121
- node.right = this.removeNode(node.right, value);
122
- return node;
123
- } else {
124
- // Node to delete found
125
- // Case 1: Leaf node
126
- if (node.left === null && node.right === null) {
127
- return null;
128
- }
129
- // Case 2: Node with one child
130
- if (node.left === null) return node.right;
131
- if (node.right === null) return node.left;
132
- // Case 3: Node with two children
133
- const minNode = this.findMin(node.right);
134
- node.value = minNode.value;
135
- node.right = this.removeNode(node.right, minNode.value);
136
- return node;
137
- }
138
- }
139
-
140
- private findMin(node: TreeNode<T>): TreeNode<T> {
141
- let current = node;
142
- while (current.left !== null) {
143
- current = current.left;
144
- }
145
- return current;
146
- }
147
-
148
- private isEqual(a: T, b: T): boolean {
149
- // Two values are equal if neither is less than the other
150
- return !this.comparator(a, b) && !this.comparator(b, a);
151
- }
152
-
153
- /**
154
- * Executes a callback function for each element in the BST in-order traversal
155
- */
156
- forEach(callback: (element: T) => void, traversal: 'inorder' | 'preorder' | 'postorder' = 'inorder'): void {
157
- switch (traversal) {
158
- case 'inorder':
159
- this.inorderTraversal(this.root, callback);
160
- break;
161
- case 'preorder':
162
- this.preorderTraversal(this.root, callback);
163
- break;
164
- case 'postorder':
165
- this.postorderTraversal(this.root, callback);
166
- break;
167
- default:
168
- this.inorderTraversal(this.root, callback);
169
- }
170
- }
171
-
172
- private inorderTraversal(node: TreeNode<T> | null, callback: (element: T) => void): void {
173
- if (node === null) return;
174
- this.inorderTraversal(node.left, callback);
175
- callback(node.value);
176
- this.inorderTraversal(node.right, callback);
177
- }
178
-
179
- private preorderTraversal(node: TreeNode<T> | null, callback: (element: T) => void): void {
180
- if (node === null) return;
181
- callback(node.value);
182
- this.preorderTraversal(node.left, callback);
183
- this.preorderTraversal(node.right, callback);
184
- }
185
-
186
- private postorderTraversal(node: TreeNode<T> | null, callback: (element: T) => void): void {
187
- if (node === null) return;
188
- this.postorderTraversal(node.left, callback);
189
- this.postorderTraversal(node.right, callback);
190
- callback(node.value);
191
- }
192
-
193
- /**
194
- * Returns true if the BST is empty, false otherwise
195
- */
196
- isEmpty(): boolean {
197
- return this.root === null;
198
- }
199
-
200
- /**
201
- * Removes all nodes from the BST
202
- */
203
- clear(): void {
204
- this.root = null;
205
- }
206
-
207
- /**
208
- * Returns the number of nodes in the BST
209
- */
210
- count(): number {
211
- return this.countNodes(this.root);
212
- }
213
-
214
- private countNodes(node: TreeNode<T> | null): number {
215
- if (node === null) return 0;
216
- return 1 + this.countNodes(node.left) + this.countNodes(node.right);
217
- }
218
- }
package/lib/deque.ts DELETED
@@ -1,86 +0,0 @@
1
- import { LinkedList } from './linked-list';
2
-
3
-
4
- export interface Deque<T> {
5
- pushFront(element: T): void;
6
- pushBack(element: T): void;
7
- popFront(): T | undefined;
8
- popBack(): T | undefined;
9
- front(): T | undefined;
10
- back(): T | undefined;
11
- isEmpty(): boolean;
12
- size(): number;
13
- clear(): void;
14
- }
15
-
16
-
17
- export class Deque<T> implements Deque<T> {
18
- private items: LinkedList<T>;
19
-
20
- constructor() {
21
- this.items = new LinkedList<T>();
22
- }
23
-
24
- /**
25
- * Adds an element to the front of the deque
26
- */
27
- pushFront(element: T): void {
28
- this.items.pushFront(element);
29
- }
30
-
31
- /**
32
- * Adds an element to the back of the deque
33
- */
34
- pushBack(element: T): void {
35
- this.items.pushBack(element);
36
- }
37
-
38
- /**
39
- * Removes and returns the front element from the deque, or undefined if deque is empty
40
- */
41
- popFront(): T | undefined {
42
- return this.items.popFront();
43
- }
44
-
45
- /**
46
- * Removes and returns the back element from the deque, or undefined if deque is empty
47
- */
48
- popBack(): T | undefined {
49
- return this.items.popBack();
50
- }
51
-
52
- /**
53
- * Returns the front element without removing it, or undefined if deque is empty
54
- */
55
- front(): T | undefined {
56
- return this.items.get(0);
57
- }
58
-
59
- /**
60
- * Returns the back element without removing it, or undefined if deque is empty
61
- */
62
- back(): T | undefined {
63
- return this.items.get(this.items.size() - 1);
64
- }
65
-
66
- /**
67
- * Returns true if the deque is empty, false otherwise
68
- */
69
- isEmpty(): boolean {
70
- return this.items.isEmpty();
71
- }
72
-
73
- /**
74
- * Returns the number of elements in the deque
75
- */
76
- size(): number {
77
- return this.items.size();
78
- }
79
-
80
- /**
81
- * Removes all elements from the deque
82
- */
83
- clear(): void {
84
- this.items.clear();
85
- }
86
- }
package/lib/hash-table.ts DELETED
@@ -1,179 +0,0 @@
1
- export interface HashTable<K, V> {
2
- insert(key: K, value: V): void;
3
- get(key: K): V | undefined;
4
- remove(key: K): boolean;
5
- size(): number;
6
- isEmpty(): boolean;
7
- clear(): void;
8
- }
9
-
10
-
11
- class HashNode<K, V> {
12
- key: K;
13
- value: V;
14
- next: HashNode<K, V> | null;
15
-
16
- constructor(key: K, value: V) {
17
- this.key = key;
18
- this.value = value;
19
- this.next = null;
20
- }
21
- }
22
-
23
- export class HashTable<K, V> implements HashTable<K, V> {
24
- private table: Array<HashNode<K, V> | null>;
25
- private count: number;
26
- private readonly capacity: number;
27
-
28
- constructor(capacity: number = 32) {
29
- this.table = new Array(capacity).fill(null);
30
- this.count = 0;
31
- this.capacity = capacity;
32
- }
33
-
34
- private hash(key: K): number {
35
- if (typeof (key as any).hashCode === 'function') {
36
- return (key as any).hashCode();
37
- }
38
-
39
- let stringKey: string;
40
- switch (typeof key) {
41
- case 'number':
42
- // If the number is a safe integer, use Knuth's multiplicative method.
43
- if (Number.isSafeInteger(key)) {
44
- const knuthConstant = 2654435761;
45
- return (Math.abs(key * knuthConstant) >>> 0) % this.capacity;
46
- }
47
- stringKey = key.toString();
48
- break;
49
- case 'object':
50
- if (key === null) {
51
- stringKey = 'null';
52
- } else if (typeof (key as any).toString === 'function') {
53
- stringKey = (key as any).toString();
54
- } else {
55
- stringKey = JSON.stringify(key);
56
- }
57
- break;
58
- case 'string':
59
- stringKey = key;
60
- break;
61
- case 'function':
62
- stringKey = key.toString();
63
- break;
64
- case 'symbol':
65
- stringKey = key.toString();
66
- break;
67
- case 'undefined':
68
- stringKey = 'null';
69
- break;
70
- default:
71
- stringKey = String(key);
72
- }
73
- let hash = 0;
74
- // DJB2 hash algorithm
75
- for (let i = 0; i < stringKey.length; i++) {
76
- hash = ((hash << 5) + hash) + stringKey.charCodeAt(i);
77
- hash = hash >>> 0; // Convert to 32-bit unsigned integer
78
- }
79
- return hash % this.capacity;
80
- }
81
-
82
- insert(key: K, value: V): void {
83
- const index = this.hash(key);
84
- const newNode = new HashNode(key, value);
85
- if (!this.table[index]) {
86
- this.table[index] = newNode;
87
- this.count++;
88
- return;
89
- }
90
- let current = this.table[index];
91
- while (current) {
92
- if (this.keysEqual(current.key, key)) {
93
- current.value = value;
94
- return;
95
- }
96
- if (!current.next) {
97
- current.next = newNode;
98
- this.count++;
99
- return;
100
- }
101
- current = current.next;
102
- }
103
- }
104
-
105
- get(key: K): V | undefined {
106
- const index = this.hash(key);
107
- let current = this.table[index];
108
- while (current) {
109
- if (this.keysEqual(current.key, key)) {
110
- return current.value;
111
- }
112
- current = current.next;
113
- }
114
- return undefined;
115
- }
116
-
117
- remove(key: K): boolean {
118
- const index = this.hash(key);
119
- let current = this.table[index];
120
- let prev: HashNode<K, V> | null = null;
121
- while (current) {
122
- if (this.keysEqual(current.key, key)) {
123
- if (prev) {
124
- prev.next = current.next;
125
- } else {
126
- this.table[index] = current.next;
127
- }
128
- this.count--;
129
- return true;
130
- }
131
- prev = current;
132
- current = current.next;
133
- }
134
- return false;
135
- }
136
-
137
- private keysEqual(key1: K, key2: K): boolean {
138
- // Check if keys have equals method and use it for comparison
139
- if (typeof (key1 as any).equals === 'function') {
140
- return (key1 as any).equals(key2);
141
- }
142
- if (key1 === key2) return true;
143
- if (key1 == null || key2 == null) return false;
144
-
145
- if (typeof key1 !== 'object' && typeof key2 !== 'object') {
146
- return key1 === key2;
147
- }
148
- if (key1 instanceof Date && key2 instanceof Date) {
149
- return key1.getTime() === key2.getTime();
150
- }
151
- if (key1 instanceof RegExp && key2 instanceof RegExp) {
152
- return key1.toString() === key2.toString();
153
- }
154
- if (Array.isArray(key1) && Array.isArray(key2)) {
155
- return key1.length === key2.length &&
156
- key1.every((val, idx) => this.keysEqual(val, key2[idx]));
157
- }
158
- if (typeof key1 === 'object' && typeof key2 === 'object') {
159
- const keys1 = Object.keys(key1);
160
- const keys2 = Object.keys(key2);
161
- return keys1.length === keys2.length &&
162
- keys1.every(k => k in key2 && this.keysEqual((key1 as any)[k], (key2 as any)[k]));
163
- }
164
- return false;
165
- }
166
-
167
- size(): number {
168
- return this.count;
169
- }
170
-
171
- isEmpty(): boolean {
172
- return this.count === 0;
173
- }
174
-
175
- clear(): void {
176
- this.table = new Array(this.capacity).fill(null);
177
- this.count = 0;
178
- }
179
- }