typescript-ds-lib 0.2.9 → 0.3.0
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 +2 -1
- package/dist/benchmarks/benchmark.d.ts +5 -0
- package/dist/benchmarks/benchmark.js +23 -0
- package/dist/benchmarks/benchmark.js.map +1 -0
- package/dist/benchmarks/hash-table.d.ts +8 -0
- package/dist/benchmarks/hash-table.js +121 -0
- package/dist/benchmarks/hash-table.js.map +1 -0
- package/dist/benchmarks/run.d.ts +1 -0
- package/dist/benchmarks/run.js +12 -0
- package/dist/benchmarks/run.js.map +1 -0
- package/dist/lib/hash-table-utils.d.ts +2 -0
- package/dist/lib/hash-table-utils.js +26 -9
- package/dist/lib/hash-table-utils.js.map +1 -1
- package/dist/lib/hash-table.js +16 -12
- package/dist/lib/hash-table.js.map +1 -1
- package/package.json +20 -3
package/README.md
CHANGED
|
@@ -48,10 +48,11 @@ See the [documentation](https://github.com/baloian/typescript-ds-lib/blob/master
|
|
|
48
48
|
- Deque
|
|
49
49
|
- Set
|
|
50
50
|
- Map
|
|
51
|
-
- Hash Table
|
|
51
|
+
- Hash Table (unordered map)
|
|
52
52
|
- Matrix
|
|
53
53
|
- Graph (coming soon)
|
|
54
54
|
|
|
55
|
+
**Note:** The `Map` data structure is implemented as a Red-Black Tree and the `Set` data structure is implemented as a Binary Search Tree.
|
|
55
56
|
|
|
56
57
|
## Contributions
|
|
57
58
|
Contributions are welcome and can be made by submitting GitHub pull requests
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class BenchmarkBase {
|
|
4
|
+
measure(fn) {
|
|
5
|
+
const start = performance.now();
|
|
6
|
+
fn();
|
|
7
|
+
const end = performance.now();
|
|
8
|
+
return end - start;
|
|
9
|
+
}
|
|
10
|
+
formatResult(name, firstTime, secondTime, firstName = 'First', secondName = 'Second') {
|
|
11
|
+
const diff = Math.abs(firstTime - secondTime);
|
|
12
|
+
const ratio = Math.max(firstTime, secondTime) / Math.min(firstTime, secondTime);
|
|
13
|
+
const faster = secondTime > firstTime ? 'slower' : 'faster';
|
|
14
|
+
const percentage = ((ratio - 1) * 100).toFixed(2);
|
|
15
|
+
console.log(`\n${name} Times:`);
|
|
16
|
+
console.log(`${firstName}: ${firstTime.toFixed(2)}ms`);
|
|
17
|
+
console.log(`${secondName}: ${secondTime.toFixed(2)}ms`);
|
|
18
|
+
// console.log(`Difference: ${diff.toFixed(2)}ms`);
|
|
19
|
+
console.log(`${secondName} is ${ratio.toFixed(2)}x (${percentage}%) ${faster} than ${firstName}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.default = BenchmarkBase;
|
|
23
|
+
//# sourceMappingURL=benchmark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmark.js","sourceRoot":"","sources":["../../benchmarks/benchmark.ts"],"names":[],"mappings":";;AAAA,MAA8B,aAAa;IAC/B,OAAO,CAAC,EAAc;QAC9B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,EAAE,EAAE,CAAC;QACL,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAC9B,OAAO,GAAG,GAAG,KAAK,CAAC;IACrB,CAAC;IAES,YAAY,CAAC,IAAY,EAAE,SAAiB,EAAE,UAAkB,EAAE,YAAoB,OAAO,EAAE,aAAqB,QAAQ;QACpI,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC5D,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAElD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,KAAK,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,KAAK,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzD,mDAAmD;QACnD,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,UAAU,MAAM,MAAM,SAAS,SAAS,EAAE,CAAC,CAAC;IACpG,CAAC;CAGF;AAtBD,gCAsBC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import BenchmarkBase from './benchmark';
|
|
2
|
+
export default class HashTableBenchmark extends BenchmarkBase {
|
|
3
|
+
protected iterations: number;
|
|
4
|
+
constructor(iterations?: number);
|
|
5
|
+
protected generateTestData(): [string, string][];
|
|
6
|
+
run(): void;
|
|
7
|
+
benchmarkCustomHashCode(): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const benchmark_1 = __importDefault(require("./benchmark"));
|
|
7
|
+
const hash_table_1 = require("../lib/hash-table");
|
|
8
|
+
class HashTableBenchmark extends benchmark_1.default {
|
|
9
|
+
iterations;
|
|
10
|
+
constructor(iterations = 100000) {
|
|
11
|
+
super();
|
|
12
|
+
this.iterations = iterations;
|
|
13
|
+
}
|
|
14
|
+
generateTestData() {
|
|
15
|
+
return Array.from({ length: this.iterations }, (_, i) => [`key${i}`, `value${i}`]);
|
|
16
|
+
}
|
|
17
|
+
run() {
|
|
18
|
+
const testData = this.generateTestData();
|
|
19
|
+
// Test insertion
|
|
20
|
+
const map = new Map();
|
|
21
|
+
const hashTable = new hash_table_1.HashTable(8192 * 100);
|
|
22
|
+
const mapInsertTime = this.measure(() => {
|
|
23
|
+
for (const [key, value] of testData) {
|
|
24
|
+
map.set(key, value);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
const hashTableInsertTime = this.measure(() => {
|
|
28
|
+
for (const [key, value] of testData) {
|
|
29
|
+
hashTable.insert(key, value);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
// Test lookup
|
|
33
|
+
const mapLookupTime = this.measure(() => {
|
|
34
|
+
for (const [key] of testData) {
|
|
35
|
+
map.get(key);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const hashTableLookupTime = this.measure(() => {
|
|
39
|
+
for (const [key] of testData) {
|
|
40
|
+
hashTable.get(key);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
// Test deletion
|
|
44
|
+
const mapDeleteTime = this.measure(() => {
|
|
45
|
+
for (const [key] of testData) {
|
|
46
|
+
map.delete(key);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
const hashTableDeleteTime = this.measure(() => {
|
|
50
|
+
for (const [key] of testData) {
|
|
51
|
+
hashTable.remove(key);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
// Print results
|
|
55
|
+
console.log(`\nBenchmark Results (${this.iterations.toLocaleString()} operations):`);
|
|
56
|
+
this.formatResult('Insertion', mapInsertTime, hashTableInsertTime, 'Map', 'HashTable');
|
|
57
|
+
// this.formatResult('Lookup', mapLookupTime, hashTableLookupTime, 'Map', 'HashTable');
|
|
58
|
+
// this.formatResult('Deletion', mapDeleteTime, hashTableDeleteTime, 'Map', 'HashTable');
|
|
59
|
+
}
|
|
60
|
+
benchmarkCustomHashCode() {
|
|
61
|
+
// Create test data with custom hash code implementation
|
|
62
|
+
class CustomKey {
|
|
63
|
+
value;
|
|
64
|
+
constructor(value) {
|
|
65
|
+
this.value = value;
|
|
66
|
+
}
|
|
67
|
+
hashCode() {
|
|
68
|
+
return this.value % 8192;
|
|
69
|
+
}
|
|
70
|
+
equals(other) {
|
|
71
|
+
return this.value === other.value;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const testData = [];
|
|
75
|
+
for (let i = 0; i < this.iterations; i++) {
|
|
76
|
+
testData.push([new CustomKey(i), i]);
|
|
77
|
+
}
|
|
78
|
+
// Test insertion
|
|
79
|
+
const map = new Map();
|
|
80
|
+
const hashTable = new hash_table_1.HashTable(8192 * 100);
|
|
81
|
+
const mapInsertTime = this.measure(() => {
|
|
82
|
+
for (const [key, value] of testData) {
|
|
83
|
+
map.set(key, value);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
const hashTableInsertTime = this.measure(() => {
|
|
87
|
+
for (const [key, value] of testData) {
|
|
88
|
+
hashTable.insert(key, value);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
// Test lookup
|
|
92
|
+
const mapLookupTime = this.measure(() => {
|
|
93
|
+
for (const [key] of testData) {
|
|
94
|
+
map.get(key);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
const hashTableLookupTime = this.measure(() => {
|
|
98
|
+
for (const [key] of testData) {
|
|
99
|
+
hashTable.get(key);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
// Test deletion
|
|
103
|
+
const mapDeleteTime = this.measure(() => {
|
|
104
|
+
for (const [key] of testData) {
|
|
105
|
+
map.delete(key);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
const hashTableDeleteTime = this.measure(() => {
|
|
109
|
+
for (const [key] of testData) {
|
|
110
|
+
hashTable.remove(key);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
// Print results
|
|
114
|
+
console.log(`\nBenchmark Results with Custom HashCode (${this.iterations.toLocaleString()} operations):`);
|
|
115
|
+
this.formatResult('Insertion', mapInsertTime, hashTableInsertTime, 'Map', 'HashTable');
|
|
116
|
+
this.formatResult('Lookup', mapLookupTime, hashTableLookupTime, 'Map', 'HashTable');
|
|
117
|
+
this.formatResult('Deletion', mapDeleteTime, hashTableDeleteTime, 'Map', 'HashTable');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.default = HashTableBenchmark;
|
|
121
|
+
//# sourceMappingURL=hash-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-table.js","sourceRoot":"","sources":["../../benchmarks/hash-table.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const hash_table_1 = __importDefault(require("./hash-table"));
|
|
7
|
+
// Run benchmark
|
|
8
|
+
console.log('Starting benchmark...');
|
|
9
|
+
const benchmark = new hash_table_1.default(100000);
|
|
10
|
+
benchmark.run();
|
|
11
|
+
// benchmark.benchmarkCustomHashCode();
|
|
12
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../benchmarks/run.ts"],"names":[],"mappings":";;;;;AAAA,8DAA8C;AAE9C,gBAAgB;AAChB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AACrC,MAAM,SAAS,GAAG,IAAI,oBAAkB,CAAC,MAAM,CAAC,CAAC;AACjD,SAAS,CAAC,GAAG,EAAE,CAAC;AAChB,uCAAuC"}
|
|
@@ -32,22 +32,39 @@ class HashTableUtils {
|
|
|
32
32
|
}
|
|
33
33
|
return stringKey;
|
|
34
34
|
}
|
|
35
|
+
// Thomas Wang, Integer Hash Functions.
|
|
36
|
+
static wangHash32(key) {
|
|
37
|
+
key = key >>> 0;
|
|
38
|
+
key = ~key + (key << 15);
|
|
39
|
+
key = key ^ (key >>> 12);
|
|
40
|
+
key = key + (key << 2);
|
|
41
|
+
key = key ^ (key >>> 4);
|
|
42
|
+
// Ensure multiplication wraps to 32 bits
|
|
43
|
+
key = ((key << 11) + (key << 3) + key) >>> 0;
|
|
44
|
+
key = key ^ (key >>> 16);
|
|
45
|
+
return key >>> 0;
|
|
46
|
+
}
|
|
47
|
+
/*
|
|
48
|
+
* DJB2a (variant using xor rather than +) hash algorithm.
|
|
49
|
+
* See: http://www.cse.yorku.ca/~oz/hash.html
|
|
50
|
+
*/
|
|
51
|
+
static hashFunction(str) {
|
|
52
|
+
let hash = 5381;
|
|
53
|
+
for (let i = 0; i < str.length; i++) {
|
|
54
|
+
hash = ((hash << 5) + hash) ^ str.charCodeAt(i);
|
|
55
|
+
}
|
|
56
|
+
// Convert the hash to an unsigned 32-bit integer to match C's unsigned long.
|
|
57
|
+
return hash >>> 0;
|
|
58
|
+
}
|
|
35
59
|
static hash(key, capacity) {
|
|
36
60
|
if (key && typeof key.hashCode === 'function') {
|
|
37
61
|
return key.hashCode();
|
|
38
62
|
}
|
|
39
63
|
if (typeof key === 'number' && Number.isSafeInteger(key)) {
|
|
40
|
-
|
|
41
|
-
return (Math.abs(key * knuthConstant) >>> 0) % capacity;
|
|
64
|
+
return HashTableUtils.wangHash32(key) % capacity;
|
|
42
65
|
}
|
|
43
66
|
const stringKey = this.valueToString(key);
|
|
44
|
-
|
|
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;
|
|
67
|
+
return this.hashFunction(stringKey) % capacity;
|
|
51
68
|
}
|
|
52
69
|
static keysEqual(key1, key2) {
|
|
53
70
|
if (key1 && key2 && typeof key1.equals === 'function') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash-table-utils.js","sourceRoot":"","sources":["../../lib/hash-table-utils.ts"],"names":[],"mappings":";;;AAAA,MAAa,cAAc;IACjB,MAAM,CAAC,aAAa,CAAI,KAAQ;QACtC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;QACzD,IAAI,SAAiB,CAAC;QACtB,QAAQ,OAAO,KAAK,EAAE,CAAC;YACrB,KAAK,QAAQ;gBACX,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC7B,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,OAAQ,KAAa,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;oBAClD,SAAS,GAAI,KAAa,CAAC,QAAQ,EAAE,CAAC;gBACxC,CAAC;qBAAM,CAAC;oBACN,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBACpC,CAAC;gBACD,MAAM;YACR,KAAK,QAAQ;gBACX,SAAS,GAAG,KAAK,CAAC;gBAClB,MAAM;YACR,KAAK,UAAU;gBACb,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC7B,MAAM;YACR,KAAK,QAAQ;gBACX,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC7B,MAAM;YACR;gBACE,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,
|
|
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.js
CHANGED
|
@@ -16,33 +16,37 @@ class HashTable {
|
|
|
16
16
|
table;
|
|
17
17
|
count;
|
|
18
18
|
capacity;
|
|
19
|
-
constructor(capacity =
|
|
19
|
+
constructor(capacity = 4096) {
|
|
20
20
|
// Handle negative or zero capacity by using default capacity
|
|
21
|
-
this.capacity = capacity <= 0 ?
|
|
21
|
+
this.capacity = capacity <= 0 ? 4096 : capacity;
|
|
22
22
|
this.table = new Array(this.capacity).fill(null);
|
|
23
23
|
this.count = 0;
|
|
24
24
|
}
|
|
25
25
|
insert(key, value) {
|
|
26
26
|
const index = hash_table_utils_1.HashTableUtils.hash(key, this.capacity);
|
|
27
|
-
|
|
27
|
+
// Handle empty bucket case.
|
|
28
28
|
if (!this.table[index]) {
|
|
29
|
-
this.table[index] =
|
|
29
|
+
this.table[index] = new HashNode(key, value);
|
|
30
30
|
this.count++;
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
+
// Check first node for key match. If it matches, update the value.
|
|
34
|
+
if (hash_table_utils_1.HashTableUtils.keysEqual(this.table[index].key, key)) {
|
|
35
|
+
this.table[index].value = value;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// Traverse chain to find key or last node. If it matches, update the value.
|
|
33
39
|
let current = this.table[index];
|
|
34
|
-
while (current) {
|
|
35
|
-
if (hash_table_utils_1.HashTableUtils.keysEqual(current.key, key)) {
|
|
36
|
-
current.value = value;
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (!current.next) {
|
|
40
|
-
current.next = newNode;
|
|
41
|
-
this.count++;
|
|
40
|
+
while (current.next) {
|
|
41
|
+
if (hash_table_utils_1.HashTableUtils.keysEqual(current.next.key, key)) {
|
|
42
|
+
current.next.value = value;
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
45
|
current = current.next;
|
|
45
46
|
}
|
|
47
|
+
// Key not found, append new node.
|
|
48
|
+
current.next = new HashNode(key, value);
|
|
49
|
+
this.count++;
|
|
46
50
|
}
|
|
47
51
|
get(key) {
|
|
48
52
|
const index = hash_table_utils_1.HashTableUtils.hash(key, this.capacity);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash-table.js","sourceRoot":"","sources":["../../lib/hash-table.ts"],"names":[],"mappings":";;;AAAA,yDAAoD;AAapD,MAAM,QAAQ;IACZ,GAAG,CAAI;IACP,KAAK,CAAI;IACT,IAAI,CAAwB;IAE5B,YAAY,GAAM,EAAE,KAAQ;QAC1B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAGD,MAAa,SAAS;IACZ,KAAK,CAA+B;IACpC,KAAK,CAAS;IACL,QAAQ,CAAS;IAElC,YAAY,WAAmB,
|
|
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.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A collection of TypeScript data structure implementations",
|
|
5
5
|
"author": "Artiom Baloian <artiom.baloian@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"build": "rm -rf dist && tsc",
|
|
16
16
|
"prepare": "npm run build",
|
|
17
|
-
"test": "rm -rf dist && tsc && jest"
|
|
17
|
+
"test": "rm -rf dist && tsc && jest",
|
|
18
|
+
"benchmark": "ts-node benchmarks/run.ts"
|
|
18
19
|
},
|
|
19
20
|
"repository": {
|
|
20
21
|
"type": "git",
|
|
@@ -26,5 +27,21 @@
|
|
|
26
27
|
"@types/node": "^22.10.1",
|
|
27
28
|
"ts-jest": "^29.2.5",
|
|
28
29
|
"typescript": "^5.7.2"
|
|
29
|
-
}
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"typescript",
|
|
33
|
+
"data-structures",
|
|
34
|
+
"algorithms",
|
|
35
|
+
"binary-search-tree",
|
|
36
|
+
"linked-list",
|
|
37
|
+
"hash-table",
|
|
38
|
+
"queue",
|
|
39
|
+
"stack",
|
|
40
|
+
"deque",
|
|
41
|
+
"priority-queue",
|
|
42
|
+
"red-black-tree",
|
|
43
|
+
"set",
|
|
44
|
+
"map",
|
|
45
|
+
"matrix"
|
|
46
|
+
]
|
|
30
47
|
}
|