typescript-ds-lib 0.2.7 → 0.2.9
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/README.md +9 -5
- package/dist/index.d.ts +6 -5
- package/dist/index.js +13 -11
- package/dist/index.js.map +1 -1
- package/dist/lib/graph.d.ts +14 -0
- package/dist/lib/graph.js +3 -0
- package/dist/lib/graph.js.map +1 -0
- package/dist/lib/hash-table-utils.d.ts +5 -0
- package/dist/lib/hash-table-utils.js +91 -0
- package/dist/lib/hash-table-utils.js.map +1 -0
- package/dist/lib/hash-table.d.ts +0 -2
- package/dist/lib/hash-table.js +10 -86
- package/dist/lib/hash-table.js.map +1 -1
- package/package.json +2 -4
- package/lib/binary-search-tree.ts +0 -218
- package/lib/deque.ts +0 -86
- package/lib/hash-table.ts +0 -179
- package/lib/linked-list.ts +0 -314
- package/lib/map.ts +0 -55
- package/lib/matrix.ts +0 -427
- package/lib/priority-queue.ts +0 -71
- package/lib/queue.ts +0 -62
- package/lib/red-black-tree.ts +0 -350
- package/lib/set.ts +0 -83
- package/lib/stack.ts +0 -59
- package/types/index.ts +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# TypeScript Data Structure Library
|
|
2
2
|
[](https://www.npmjs.com/package/typescript-ds-lib)
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
Provides Comparator for custom types. Just pass your own comparator function to the constructor.
|
|
4
|
+
TypeScript data structure implementations without external dependencies. Why to use this library?
|
|
6
5
|
|
|
7
6
|
- Fully Tested
|
|
8
7
|
- Fast
|
|
@@ -11,11 +10,13 @@ Provides Comparator for custom types. Just pass your own comparator function to
|
|
|
11
10
|
- Comes with Comparator (for custom types)
|
|
12
11
|
- `hashCode()` and `equals()` are supported
|
|
13
12
|
|
|
13
|
+
|
|
14
14
|
## Install
|
|
15
15
|
```
|
|
16
16
|
npm install typescript-ds-lib
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
|
|
19
20
|
## Usage
|
|
20
21
|
```typescript
|
|
21
22
|
import { Stack } from 'typescript-ds-lib';
|
|
@@ -32,6 +33,11 @@ console.log(stack.top()); // 2
|
|
|
32
33
|
console.log(stack.size()); // 2
|
|
33
34
|
```
|
|
34
35
|
|
|
36
|
+
|
|
37
|
+
## Documentation and Examples
|
|
38
|
+
See the [documentation](https://github.com/baloian/typescript-ds-lib/blob/master/doc/DOCUMENTATION.md) for more details and examples.
|
|
39
|
+
|
|
40
|
+
|
|
35
41
|
## Data Structures
|
|
36
42
|
- Stack
|
|
37
43
|
- Queue
|
|
@@ -44,11 +50,9 @@ console.log(stack.size()); // 2
|
|
|
44
50
|
- Map
|
|
45
51
|
- Hash Table
|
|
46
52
|
- Matrix
|
|
53
|
+
- Graph (coming soon)
|
|
47
54
|
|
|
48
55
|
|
|
49
|
-
## Documentation and Examples
|
|
50
|
-
See the [documentation](https://github.com/baloian/typescript-ds-lib/blob/master/doc/DOCUMENTATION.md) for more details and examples.
|
|
51
|
-
|
|
52
56
|
## Contributions
|
|
53
57
|
Contributions are welcome and can be made by submitting GitHub pull requests
|
|
54
58
|
to this repository. In general, the source code follows
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export * from './types';
|
|
2
|
-
export { Stack } from './lib/stack';
|
|
3
|
-
export { Queue } from './lib/queue';
|
|
4
|
-
export { PriorityQueue } from './lib/priority-queue';
|
|
5
2
|
export { BinarySearchTree } from './lib/binary-search-tree';
|
|
6
3
|
export { Deque } from './lib/deque';
|
|
4
|
+
export { HashTable } from './lib/hash-table';
|
|
7
5
|
export { LinkedList } from './lib/linked-list';
|
|
8
|
-
export { Set } from './lib/set';
|
|
9
6
|
export { Map } from './lib/map';
|
|
7
|
+
export { Matrix } from './lib/matrix';
|
|
8
|
+
export { PriorityQueue } from './lib/priority-queue';
|
|
9
|
+
export { Queue } from './lib/queue';
|
|
10
10
|
export { RedBlackTree } from './lib/red-black-tree';
|
|
11
|
-
export {
|
|
11
|
+
export { Set } from './lib/set';
|
|
12
|
+
export { Stack } from './lib/stack';
|
package/dist/index.js
CHANGED
|
@@ -14,26 +14,28 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
17
|
+
exports.Stack = exports.Set = exports.RedBlackTree = exports.Queue = exports.PriorityQueue = exports.Matrix = exports.Map = exports.LinkedList = exports.HashTable = exports.Deque = exports.BinarySearchTree = void 0;
|
|
18
18
|
__exportStar(require("./types"), exports);
|
|
19
|
-
var stack_1 = require("./lib/stack");
|
|
20
|
-
Object.defineProperty(exports, "Stack", { enumerable: true, get: function () { return stack_1.Stack; } });
|
|
21
|
-
var queue_1 = require("./lib/queue");
|
|
22
|
-
Object.defineProperty(exports, "Queue", { enumerable: true, get: function () { return queue_1.Queue; } });
|
|
23
|
-
var priority_queue_1 = require("./lib/priority-queue");
|
|
24
|
-
Object.defineProperty(exports, "PriorityQueue", { enumerable: true, get: function () { return priority_queue_1.PriorityQueue; } });
|
|
25
19
|
var binary_search_tree_1 = require("./lib/binary-search-tree");
|
|
26
20
|
Object.defineProperty(exports, "BinarySearchTree", { enumerable: true, get: function () { return binary_search_tree_1.BinarySearchTree; } });
|
|
27
21
|
var deque_1 = require("./lib/deque");
|
|
28
22
|
Object.defineProperty(exports, "Deque", { enumerable: true, get: function () { return deque_1.Deque; } });
|
|
23
|
+
var hash_table_1 = require("./lib/hash-table");
|
|
24
|
+
Object.defineProperty(exports, "HashTable", { enumerable: true, get: function () { return hash_table_1.HashTable; } });
|
|
29
25
|
var linked_list_1 = require("./lib/linked-list");
|
|
30
26
|
Object.defineProperty(exports, "LinkedList", { enumerable: true, get: function () { return linked_list_1.LinkedList; } });
|
|
31
|
-
var set_1 = require("./lib/set");
|
|
32
|
-
Object.defineProperty(exports, "Set", { enumerable: true, get: function () { return set_1.Set; } });
|
|
33
27
|
var map_1 = require("./lib/map");
|
|
34
28
|
Object.defineProperty(exports, "Map", { enumerable: true, get: function () { return map_1.Map; } });
|
|
29
|
+
var matrix_1 = require("./lib/matrix");
|
|
30
|
+
Object.defineProperty(exports, "Matrix", { enumerable: true, get: function () { return matrix_1.Matrix; } });
|
|
31
|
+
var priority_queue_1 = require("./lib/priority-queue");
|
|
32
|
+
Object.defineProperty(exports, "PriorityQueue", { enumerable: true, get: function () { return priority_queue_1.PriorityQueue; } });
|
|
33
|
+
var queue_1 = require("./lib/queue");
|
|
34
|
+
Object.defineProperty(exports, "Queue", { enumerable: true, get: function () { return queue_1.Queue; } });
|
|
35
35
|
var red_black_tree_1 = require("./lib/red-black-tree");
|
|
36
36
|
Object.defineProperty(exports, "RedBlackTree", { enumerable: true, get: function () { return red_black_tree_1.RedBlackTree; } });
|
|
37
|
-
var
|
|
38
|
-
Object.defineProperty(exports, "
|
|
37
|
+
var set_1 = require("./lib/set");
|
|
38
|
+
Object.defineProperty(exports, "Set", { enumerable: true, get: function () { return set_1.Set; } });
|
|
39
|
+
var stack_1 = require("./lib/stack");
|
|
40
|
+
Object.defineProperty(exports, "Stack", { enumerable: true, get: function () { return stack_1.Stack; } });
|
|
39
41
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,+DAA4D;AAAnD,sHAAA,gBAAgB,OAAA;AACzB,qCAAoC;AAA3B,8FAAA,KAAK,OAAA;AACd,+CAA6C;AAApC,uGAAA,SAAS,OAAA;AAClB,iDAA+C;AAAtC,yGAAA,UAAU,OAAA;AACnB,iCAAgC;AAAvB,0FAAA,GAAG,OAAA;AACZ,uCAAsC;AAA7B,gGAAA,MAAM,OAAA;AACf,uDAAqD;AAA5C,+GAAA,aAAa,OAAA;AACtB,qCAAoC;AAA3B,8FAAA,KAAK,OAAA;AACd,uDAAoD;AAA3C,8GAAA,YAAY,OAAA;AACrB,iCAAgC;AAAvB,0FAAA,GAAG,OAAA;AACZ,qCAAoC;AAA3B,8FAAA,KAAK,OAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Graph<V, W> {
|
|
2
|
+
addVertex(vertex: V): void;
|
|
3
|
+
removeVertex(vertex: V): void;
|
|
4
|
+
addEdge(from: V, to: V, weight?: W): void;
|
|
5
|
+
removeEdge(from: V, to: V): void;
|
|
6
|
+
getNeighbors(vertex: V): V[];
|
|
7
|
+
getEdgeWeight(from: V, to: V): W;
|
|
8
|
+
getVertices(): V[];
|
|
9
|
+
hasVertex(vertex: V): boolean;
|
|
10
|
+
hasEdge(from: V, to: V): boolean;
|
|
11
|
+
vertexCount(): number;
|
|
12
|
+
edgeCount(): number;
|
|
13
|
+
clear(): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../../lib/graph.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HashTableUtils = void 0;
|
|
4
|
+
class HashTableUtils {
|
|
5
|
+
static valueToString(value) {
|
|
6
|
+
if (value === null || value === undefined)
|
|
7
|
+
return 'null';
|
|
8
|
+
let stringKey;
|
|
9
|
+
switch (typeof value) {
|
|
10
|
+
case 'number':
|
|
11
|
+
stringKey = value.toString();
|
|
12
|
+
break;
|
|
13
|
+
case 'object':
|
|
14
|
+
if (typeof value.toString === 'function') {
|
|
15
|
+
stringKey = value.toString();
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
stringKey = JSON.stringify(value);
|
|
19
|
+
}
|
|
20
|
+
break;
|
|
21
|
+
case 'string':
|
|
22
|
+
stringKey = value;
|
|
23
|
+
break;
|
|
24
|
+
case 'function':
|
|
25
|
+
stringKey = value.toString();
|
|
26
|
+
break;
|
|
27
|
+
case 'symbol':
|
|
28
|
+
stringKey = value.toString();
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
stringKey = String(value);
|
|
32
|
+
}
|
|
33
|
+
return stringKey;
|
|
34
|
+
}
|
|
35
|
+
static hash(key, capacity) {
|
|
36
|
+
if (key && typeof key.hashCode === 'function') {
|
|
37
|
+
return key.hashCode();
|
|
38
|
+
}
|
|
39
|
+
if (typeof key === 'number' && Number.isSafeInteger(key)) {
|
|
40
|
+
const knuthConstant = 2654435761;
|
|
41
|
+
return (Math.abs(key * knuthConstant) >>> 0) % capacity;
|
|
42
|
+
}
|
|
43
|
+
const stringKey = this.valueToString(key);
|
|
44
|
+
let hash = 0;
|
|
45
|
+
// DJB2 hash algorithm
|
|
46
|
+
for (let i = 0; i < stringKey.length; i++) {
|
|
47
|
+
hash = ((hash << 5) + hash) + stringKey.charCodeAt(i);
|
|
48
|
+
hash = hash >>> 0; // Convert to 32-bit unsigned integer
|
|
49
|
+
}
|
|
50
|
+
return hash % capacity;
|
|
51
|
+
}
|
|
52
|
+
static keysEqual(key1, key2) {
|
|
53
|
+
if (key1 && key2 && typeof key1.equals === 'function') {
|
|
54
|
+
return key1.equals(key2);
|
|
55
|
+
}
|
|
56
|
+
if (key1 === key2)
|
|
57
|
+
return true;
|
|
58
|
+
if (typeof key1 === 'number' && typeof key2 === 'number' && isNaN(key1) && isNaN(key2))
|
|
59
|
+
return true;
|
|
60
|
+
if (typeof key1 !== 'object' && typeof key2 !== 'object')
|
|
61
|
+
return key1 === key2;
|
|
62
|
+
if (key1 instanceof Date && key2 instanceof Date) {
|
|
63
|
+
// Handle invalid dates
|
|
64
|
+
if (isNaN(key1.getTime()) && isNaN(key2.getTime()))
|
|
65
|
+
return true;
|
|
66
|
+
return key1.getTime() === key2.getTime();
|
|
67
|
+
}
|
|
68
|
+
if (key1 instanceof RegExp && key2 instanceof RegExp) {
|
|
69
|
+
return key1.toString() === key2.toString();
|
|
70
|
+
}
|
|
71
|
+
if (Array.isArray(key1) && Array.isArray(key2)) {
|
|
72
|
+
return key1.length === key2.length &&
|
|
73
|
+
key1.every((val, idx) => HashTableUtils.keysEqual(val, key2[idx]));
|
|
74
|
+
}
|
|
75
|
+
if (key1 === null && key2 === null)
|
|
76
|
+
return true;
|
|
77
|
+
if (key1 === undefined && key2 === undefined)
|
|
78
|
+
return true;
|
|
79
|
+
if (key1 === null || key1 === undefined || key2 === null || key2 === undefined)
|
|
80
|
+
return false;
|
|
81
|
+
if (typeof key1 === 'object' && typeof key2 === 'object') {
|
|
82
|
+
const keys1 = Object.keys(key1);
|
|
83
|
+
const keys2 = Object.keys(key2);
|
|
84
|
+
return keys1.length === keys2.length &&
|
|
85
|
+
keys1.every(k => k in key2 && HashTableUtils.keysEqual(key1[k], key2[k]));
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.HashTableUtils = HashTableUtils;
|
|
91
|
+
//# sourceMappingURL=hash-table-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-table-utils.js","sourceRoot":"","sources":["../../lib/hash-table-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/hash-table.d.ts
CHANGED
package/dist/lib/hash-table.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HashTable = void 0;
|
|
4
|
+
const hash_table_utils_1 = require("./hash-table-utils");
|
|
4
5
|
class HashNode {
|
|
5
6
|
key;
|
|
6
7
|
value;
|
|
@@ -16,60 +17,13 @@ class HashTable {
|
|
|
16
17
|
count;
|
|
17
18
|
capacity;
|
|
18
19
|
constructor(capacity = 32) {
|
|
19
|
-
|
|
20
|
+
// Handle negative or zero capacity by using default capacity
|
|
21
|
+
this.capacity = capacity <= 0 ? 32 : capacity;
|
|
22
|
+
this.table = new Array(this.capacity).fill(null);
|
|
20
23
|
this.count = 0;
|
|
21
|
-
this.capacity = capacity;
|
|
22
|
-
}
|
|
23
|
-
hash(key) {
|
|
24
|
-
if (typeof key.hashCode === 'function') {
|
|
25
|
-
return key.hashCode();
|
|
26
|
-
}
|
|
27
|
-
let stringKey;
|
|
28
|
-
switch (typeof key) {
|
|
29
|
-
case 'number':
|
|
30
|
-
// If the number is a safe integer, use Knuth's multiplicative method.
|
|
31
|
-
if (Number.isSafeInteger(key)) {
|
|
32
|
-
const knuthConstant = 2654435761;
|
|
33
|
-
return (Math.abs(key * knuthConstant) >>> 0) % this.capacity;
|
|
34
|
-
}
|
|
35
|
-
stringKey = key.toString();
|
|
36
|
-
break;
|
|
37
|
-
case 'object':
|
|
38
|
-
if (key === null) {
|
|
39
|
-
stringKey = 'null';
|
|
40
|
-
}
|
|
41
|
-
else if (typeof key.toString === 'function') {
|
|
42
|
-
stringKey = key.toString();
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
stringKey = JSON.stringify(key);
|
|
46
|
-
}
|
|
47
|
-
break;
|
|
48
|
-
case 'string':
|
|
49
|
-
stringKey = key;
|
|
50
|
-
break;
|
|
51
|
-
case 'function':
|
|
52
|
-
stringKey = key.toString();
|
|
53
|
-
break;
|
|
54
|
-
case 'symbol':
|
|
55
|
-
stringKey = key.toString();
|
|
56
|
-
break;
|
|
57
|
-
case 'undefined':
|
|
58
|
-
stringKey = 'null';
|
|
59
|
-
break;
|
|
60
|
-
default:
|
|
61
|
-
stringKey = String(key);
|
|
62
|
-
}
|
|
63
|
-
let hash = 0;
|
|
64
|
-
// DJB2 hash algorithm
|
|
65
|
-
for (let i = 0; i < stringKey.length; i++) {
|
|
66
|
-
hash = ((hash << 5) + hash) + stringKey.charCodeAt(i);
|
|
67
|
-
hash = hash >>> 0; // Convert to 32-bit unsigned integer
|
|
68
|
-
}
|
|
69
|
-
return hash % this.capacity;
|
|
70
24
|
}
|
|
71
25
|
insert(key, value) {
|
|
72
|
-
const index =
|
|
26
|
+
const index = hash_table_utils_1.HashTableUtils.hash(key, this.capacity);
|
|
73
27
|
const newNode = new HashNode(key, value);
|
|
74
28
|
if (!this.table[index]) {
|
|
75
29
|
this.table[index] = newNode;
|
|
@@ -78,7 +32,7 @@ class HashTable {
|
|
|
78
32
|
}
|
|
79
33
|
let current = this.table[index];
|
|
80
34
|
while (current) {
|
|
81
|
-
if (
|
|
35
|
+
if (hash_table_utils_1.HashTableUtils.keysEqual(current.key, key)) {
|
|
82
36
|
current.value = value;
|
|
83
37
|
return;
|
|
84
38
|
}
|
|
@@ -91,10 +45,10 @@ class HashTable {
|
|
|
91
45
|
}
|
|
92
46
|
}
|
|
93
47
|
get(key) {
|
|
94
|
-
const index =
|
|
48
|
+
const index = hash_table_utils_1.HashTableUtils.hash(key, this.capacity);
|
|
95
49
|
let current = this.table[index];
|
|
96
50
|
while (current) {
|
|
97
|
-
if (
|
|
51
|
+
if (hash_table_utils_1.HashTableUtils.keysEqual(current.key, key)) {
|
|
98
52
|
return current.value;
|
|
99
53
|
}
|
|
100
54
|
current = current.next;
|
|
@@ -102,11 +56,11 @@ class HashTable {
|
|
|
102
56
|
return undefined;
|
|
103
57
|
}
|
|
104
58
|
remove(key) {
|
|
105
|
-
const index =
|
|
59
|
+
const index = hash_table_utils_1.HashTableUtils.hash(key, this.capacity);
|
|
106
60
|
let current = this.table[index];
|
|
107
61
|
let prev = null;
|
|
108
62
|
while (current) {
|
|
109
|
-
if (
|
|
63
|
+
if (hash_table_utils_1.HashTableUtils.keysEqual(current.key, key)) {
|
|
110
64
|
if (prev) {
|
|
111
65
|
prev.next = current.next;
|
|
112
66
|
}
|
|
@@ -121,36 +75,6 @@ class HashTable {
|
|
|
121
75
|
}
|
|
122
76
|
return false;
|
|
123
77
|
}
|
|
124
|
-
keysEqual(key1, key2) {
|
|
125
|
-
// Check if keys have equals method and use it for comparison
|
|
126
|
-
if (typeof key1.equals === 'function') {
|
|
127
|
-
return key1.equals(key2);
|
|
128
|
-
}
|
|
129
|
-
if (key1 === key2)
|
|
130
|
-
return true;
|
|
131
|
-
if (key1 == null || key2 == null)
|
|
132
|
-
return false;
|
|
133
|
-
if (typeof key1 !== 'object' && typeof key2 !== 'object') {
|
|
134
|
-
return key1 === key2;
|
|
135
|
-
}
|
|
136
|
-
if (key1 instanceof Date && key2 instanceof Date) {
|
|
137
|
-
return key1.getTime() === key2.getTime();
|
|
138
|
-
}
|
|
139
|
-
if (key1 instanceof RegExp && key2 instanceof RegExp) {
|
|
140
|
-
return key1.toString() === key2.toString();
|
|
141
|
-
}
|
|
142
|
-
if (Array.isArray(key1) && Array.isArray(key2)) {
|
|
143
|
-
return key1.length === key2.length &&
|
|
144
|
-
key1.every((val, idx) => this.keysEqual(val, key2[idx]));
|
|
145
|
-
}
|
|
146
|
-
if (typeof key1 === 'object' && typeof key2 === 'object') {
|
|
147
|
-
const keys1 = Object.keys(key1);
|
|
148
|
-
const keys2 = Object.keys(key2);
|
|
149
|
-
return keys1.length === keys2.length &&
|
|
150
|
-
keys1.every(k => k in key2 && this.keysEqual(key1[k], key2[k]));
|
|
151
|
-
}
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
78
|
size() {
|
|
155
79
|
return this.count;
|
|
156
80
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash-table.js","sourceRoot":"","sources":["../../lib/hash-table.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"hash-table.js","sourceRoot":"","sources":["../../lib/hash-table.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typescript-ds-lib",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
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
|
-
}
|