@blackglory/structures 0.14.14 → 0.15.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 +661 -92
- package/lib/async-generator-emitter.js +2 -5
- package/lib/async-generator-emitter.js.map +1 -1
- package/lib/big-map.js +1 -3
- package/lib/big-map.js.map +1 -1
- package/lib/big-set.js +1 -3
- package/lib/big-set.js.map +1 -1
- package/lib/{bit-set.d.ts → bit-set/bit-set.d.ts} +5 -2
- package/lib/{bit-set.js → bit-set/bit-set.js} +43 -34
- package/lib/bit-set/bit-set.js.map +1 -0
- package/lib/{typed-bit-set.d.ts → bit-set/dynamic-typed-bit-set.d.ts} +6 -4
- package/lib/bit-set/dynamic-typed-bit-set.js +95 -0
- package/lib/bit-set/dynamic-typed-bit-set.js.map +1 -0
- package/lib/bit-set/index.d.ts +4 -0
- package/lib/bit-set/index.js +5 -0
- package/lib/bit-set/index.js.map +1 -0
- package/lib/bit-set/resizable-typed-bit-set.d.ts +22 -0
- package/lib/{typed-bit-set.js → bit-set/resizable-typed-bit-set.js} +37 -39
- package/lib/bit-set/resizable-typed-bit-set.js.map +1 -0
- package/lib/bit-set/typed-bit-set.d.ts +22 -0
- package/lib/bit-set/typed-bit-set.js +99 -0
- package/lib/bit-set/typed-bit-set.js.map +1 -0
- package/lib/box.js +1 -0
- package/lib/box.js.map +1 -1
- package/lib/disjoint-set.js +2 -4
- package/lib/disjoint-set.js.map +1 -1
- package/lib/dynamic-typed-array.d.ts +12 -9
- package/lib/dynamic-typed-array.js +51 -66
- package/lib/dynamic-typed-array.js.map +1 -1
- package/lib/emitter.js +3 -7
- package/lib/emitter.js.map +1 -1
- package/lib/expirable-map.js +9 -15
- package/lib/expirable-map.js.map +1 -1
- package/lib/generator-emitter.js +2 -5
- package/lib/generator-emitter.js.map +1 -1
- package/lib/hash-map.js +2 -1
- package/lib/hash-map.js.map +1 -1
- package/lib/hash-set.js +2 -1
- package/lib/hash-set.js.map +1 -1
- package/lib/index.d.ts +5 -7
- package/lib/index.js +5 -7
- package/lib/index.js.map +1 -1
- package/lib/lru-map.js +2 -1
- package/lib/lru-map.js.map +1 -1
- package/lib/queue.js +1 -3
- package/lib/queue.js.map +1 -1
- package/lib/radix-tree.js +6 -7
- package/lib/radix-tree.js.map +1 -1
- package/lib/resizable-typed-array.d.ts +32 -0
- package/lib/resizable-typed-array.js +127 -0
- package/lib/resizable-typed-array.js.map +1 -0
- package/lib/sorted-set.js +2 -1
- package/lib/sorted-set.js.map +1 -1
- package/lib/sparse-map/clean-sparse-map.d.ts +18 -0
- package/lib/sparse-map/clean-sparse-map.js +74 -0
- package/lib/sparse-map/clean-sparse-map.js.map +1 -0
- package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.js +87 -0
- package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/dynamic-typed-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/dynamic-typed-sparse-map-lite.js +94 -0
- package/lib/sparse-map/dynamic-typed-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/index.d.ts +10 -0
- package/lib/sparse-map/index.js +11 -0
- package/lib/sparse-map/index.js.map +1 -0
- package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.js +85 -0
- package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/resizable-typed-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/resizable-typed-sparse-map-lite.js +92 -0
- package/lib/sparse-map/resizable-typed-sparse-map-lite.js.map +1 -0
- package/lib/{sparse-map.d.ts → sparse-map/sparse-map.d.ts} +6 -5
- package/lib/sparse-map/sparse-map.js +86 -0
- package/lib/sparse-map/sparse-map.js.map +1 -0
- package/lib/sparse-map/typed-clean-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/typed-clean-sparse-map-lite.js +92 -0
- package/lib/sparse-map/typed-clean-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/typed-clean-sparse-map.d.ts +22 -0
- package/lib/sparse-map/typed-clean-sparse-map.js +117 -0
- package/lib/sparse-map/typed-clean-sparse-map.js.map +1 -0
- package/lib/sparse-map/typed-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/typed-sparse-map-lite.js +109 -0
- package/lib/sparse-map/typed-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/typed-sparse-map.d.ts +21 -0
- package/lib/sparse-map/typed-sparse-map.js +130 -0
- package/lib/sparse-map/typed-sparse-map.js.map +1 -0
- package/lib/sparse-set/clean-sparse-set.d.ts +13 -0
- package/lib/sparse-set/clean-sparse-set.js +57 -0
- package/lib/sparse-set/clean-sparse-set.js.map +1 -0
- package/lib/{typed-sparse-set.d.ts → sparse-set/dynamic-typed-clean-sparse-set-lite.d.ts} +6 -6
- package/lib/sparse-set/dynamic-typed-clean-sparse-set-lite.js +51 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set.d.ts +16 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set.js +82 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set.js.map +1 -0
- package/lib/sparse-set/dynamic-typed-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/dynamic-typed-sparse-set-lite.js +52 -0
- package/lib/sparse-set/dynamic-typed-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/dynamic-typed-sparse-set.d.ts +15 -0
- package/lib/sparse-set/dynamic-typed-sparse-set.js +75 -0
- package/lib/sparse-set/dynamic-typed-sparse-set.js.map +1 -0
- package/lib/sparse-set/index.d.ts +14 -0
- package/lib/sparse-set/index.js +15 -0
- package/lib/sparse-set/index.js.map +1 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.js +51 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set.d.ts +16 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set.js +83 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set.js.map +1 -0
- package/lib/sparse-set/resizable-typed-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/resizable-typed-sparse-set-lite.js +52 -0
- package/lib/sparse-set/resizable-typed-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/resizable-typed-sparse-set.d.ts +15 -0
- package/lib/sparse-set/resizable-typed-sparse-set.js +76 -0
- package/lib/sparse-set/resizable-typed-sparse-set.js.map +1 -0
- package/lib/{sparse-set.d.ts → sparse-set/sparse-set.d.ts} +3 -4
- package/lib/sparse-set/sparse-set.js +60 -0
- package/lib/sparse-set/sparse-set.js.map +1 -0
- package/lib/sparse-set/typed-clean-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/typed-clean-sparse-set-lite.js +55 -0
- package/lib/sparse-set/typed-clean-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/typed-clean-sparse-set.d.ts +16 -0
- package/lib/sparse-set/typed-clean-sparse-set.js +80 -0
- package/lib/sparse-set/typed-clean-sparse-set.js.map +1 -0
- package/lib/sparse-set/typed-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/typed-sparse-set-lite.js +60 -0
- package/lib/sparse-set/typed-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/typed-sparse-set.d.ts +15 -0
- package/lib/sparse-set/typed-sparse-set.js +81 -0
- package/lib/sparse-set/typed-sparse-set.js.map +1 -0
- package/lib/string-radix-tree.js +6 -7
- package/lib/string-radix-tree.js.map +1 -1
- package/lib/string-trie-map.js +3 -4
- package/lib/string-trie-map.js.map +1 -1
- package/lib/tlru-map.js +6 -6
- package/lib/tlru-map.js.map +1 -1
- package/lib/trie-map.js +3 -4
- package/lib/trie-map.js.map +1 -1
- package/lib/unique-queue.js +1 -3
- package/lib/unique-queue.js.map +1 -1
- package/lib/utils/compute-new-capacity.d.ts +1 -0
- package/lib/utils/compute-new-capacity.js +36 -0
- package/lib/utils/compute-new-capacity.js.map +1 -0
- package/lib/utils/get-max-value-of-unsigned-typed-array.d.ts +3 -0
- package/lib/utils/get-max-value-of-unsigned-typed-array.js +13 -0
- package/lib/utils/get-max-value-of-unsigned-typed-array.js.map +1 -0
- package/lib/utils/skip-list.js +11 -9
- package/lib/utils/skip-list.js.map +1 -1
- package/lib/utils/trailing-zeros.js +1 -1
- package/lib/utils/trailing-zeros.js.map +1 -1
- package/package.json +28 -31
- package/src/{bit-set.ts → bit-set/bit-set.ts} +47 -31
- package/src/bit-set/dynamic-typed-bit-set.ts +131 -0
- package/src/bit-set/index.ts +4 -0
- package/src/{typed-bit-set.ts → bit-set/resizable-typed-bit-set.ts} +38 -36
- package/src/bit-set/typed-bit-set.ts +134 -0
- package/src/dynamic-typed-array.ts +67 -82
- package/src/index.ts +5 -7
- package/src/radix-tree.ts +3 -3
- package/src/resizable-typed-array.ts +214 -0
- package/src/sparse-map/clean-sparse-map.ts +84 -0
- package/src/sparse-map/dynamic-typed-clean-sparse-map-lite.ts +109 -0
- package/src/sparse-map/dynamic-typed-sparse-map-lite.ts +124 -0
- package/src/sparse-map/index.ts +11 -0
- package/src/sparse-map/resizable-typed-clean-sparse-map-lite.ts +107 -0
- package/src/sparse-map/resizable-typed-sparse-map-lite.ts +122 -0
- package/src/sparse-map/sparse-map.ts +104 -0
- package/src/sparse-map/typed-clean-sparse-map-lite.ts +116 -0
- package/src/sparse-map/typed-clean-sparse-map.ts +149 -0
- package/src/sparse-map/typed-sparse-map-lite.ts +141 -0
- package/src/sparse-map/typed-sparse-map.ts +169 -0
- package/src/sparse-set/clean-sparse-set.ts +76 -0
- package/src/sparse-set/dynamic-typed-clean-sparse-set-lite.ts +64 -0
- package/src/sparse-set/dynamic-typed-clean-sparse-set.ts +101 -0
- package/src/sparse-set/dynamic-typed-sparse-set-lite.ts +67 -0
- package/src/sparse-set/dynamic-typed-sparse-set.ts +93 -0
- package/src/sparse-set/index.ts +15 -0
- package/src/sparse-set/resizable-typed-clean-sparse-set-lite.ts +64 -0
- package/src/sparse-set/resizable-typed-clean-sparse-set.ts +108 -0
- package/src/sparse-set/resizable-typed-sparse-set-lite.ts +67 -0
- package/src/sparse-set/resizable-typed-sparse-set.ts +97 -0
- package/src/sparse-set/sparse-set.ts +79 -0
- package/src/sparse-set/typed-clean-sparse-set-lite.ts +67 -0
- package/src/sparse-set/typed-clean-sparse-set.ts +100 -0
- package/src/sparse-set/typed-sparse-set-lite.ts +74 -0
- package/src/sparse-set/typed-sparse-set.ts +102 -0
- package/src/string-radix-tree.ts +3 -3
- package/src/utils/compute-new-capacity.ts +39 -0
- package/src/utils/get-max-value-of-unsigned-typed-array.ts +19 -0
- package/src/utils/skip-list.ts +1 -1
- package/src/utils/trailing-zeros.ts +2 -3
- package/lib/bit-set.js.map +0 -1
- package/lib/sparse-map.js +0 -76
- package/lib/sparse-map.js.map +0 -1
- package/lib/sparse-set.js +0 -63
- package/lib/sparse-set.js.map +0 -1
- package/lib/typed-bit-set.js.map +0 -1
- package/lib/typed-sparse-map.d.ts +0 -20
- package/lib/typed-sparse-map.js +0 -83
- package/lib/typed-sparse-map.js.map +0 -1
- package/lib/typed-sparse-set.js +0 -59
- package/lib/typed-sparse-set.js.map +0 -1
- package/src/sparse-map.ts +0 -82
- package/src/sparse-set.ts +0 -74
- package/src/typed-sparse-map.ts +0 -97
- package/src/typed-sparse-set.ts +0 -73
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import { UnsignedTypedArrayConstructor } from 'justypes'
|
|
2
2
|
import { assert } from '@blackglory/errors'
|
|
3
|
-
import {
|
|
3
|
+
import { ResizableTypedArray } from '@src/resizable-typed-array.js'
|
|
4
4
|
import { trailingZeros } from '@utils/trailing-zeros.js'
|
|
5
5
|
|
|
6
|
-
export class
|
|
6
|
+
export class ResizableTypedBitSet implements Iterable<number> {
|
|
7
7
|
private bitsPerElement: number
|
|
8
8
|
private length = 0
|
|
9
|
-
|
|
9
|
+
#size = 0
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
private quotientShift = 0
|
|
12
|
+
private remainderMask = 0
|
|
13
|
+
|
|
14
|
+
get [Symbol.toStringTag](): string {
|
|
15
|
+
return this.constructor.name
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get size(): number {
|
|
19
|
+
return this.#size
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
constructor(private array: ResizableTypedArray<UnsignedTypedArrayConstructor>) {
|
|
12
23
|
const bitsPerElement = array.BYTES_PER_ELEMENT * 8
|
|
13
24
|
|
|
14
25
|
assert(
|
|
@@ -21,19 +32,13 @@ export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
|
|
|
21
32
|
)
|
|
22
33
|
// `31`是该数据结构中能够处理的最大值
|
|
23
34
|
assert(
|
|
24
|
-
bitsPerElement <=
|
|
25
|
-
, 'The
|
|
35
|
+
bitsPerElement <= 32
|
|
36
|
+
, 'The bitsPerElement must be less than or equal to 31'
|
|
26
37
|
)
|
|
27
38
|
|
|
28
39
|
this.bitsPerElement = bitsPerElement
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
get [Symbol.toStringTag](): string {
|
|
32
|
-
return this.constructor.name
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
get size(): number {
|
|
36
|
-
return this._size
|
|
40
|
+
this.quotientShift = Math.log2(bitsPerElement)
|
|
41
|
+
this.remainderMask = bitsPerElement - 1
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
[Symbol.iterator](): IterableIterator<number> {
|
|
@@ -46,13 +51,12 @@ export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
|
|
|
46
51
|
const maxArrayLength = ~~(this.length / this.bitsPerElement) + 1
|
|
47
52
|
|
|
48
53
|
for (let index = 0; index < maxArrayLength; index++) {
|
|
49
|
-
let element = this.array.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
element >>= indexOfBit + 1
|
|
54
|
+
let element = this.array.get(index) ?? 0
|
|
55
|
+
while (element !== 0) {
|
|
56
|
+
const indexOfBit = trailingZeros(element)
|
|
57
|
+
yield index * this.bitsPerElement + indexOfBit
|
|
58
|
+
// 移除最低位置的1, 以推进下一个indexOfBit的获取.
|
|
59
|
+
element &= element - 1
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
}
|
|
@@ -61,7 +65,7 @@ export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
|
|
|
61
65
|
_dumpBinaryStrings(): string[] {
|
|
62
66
|
const result: string[] = []
|
|
63
67
|
for (let i = 0; i < this.array.length; i++) {
|
|
64
|
-
const binary = this.array.
|
|
68
|
+
const binary = ((this.array.get(i) ?? 0) >>> 0).toString(2)
|
|
65
69
|
if (binary.length < this.bitsPerElement) {
|
|
66
70
|
result.push('0'.repeat(this.bitsPerElement - binary.length) + binary)
|
|
67
71
|
} else {
|
|
@@ -78,20 +82,16 @@ export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
|
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
add(value: number): boolean {
|
|
81
|
-
assert(value >= 0, 'value must be greater than or equal to 0')
|
|
82
|
-
if (value >= this.length) {
|
|
83
|
-
this.length = value + 1
|
|
84
|
-
}
|
|
85
|
-
|
|
86
85
|
const [index, mask] = this.getPosition(value)
|
|
87
86
|
|
|
88
87
|
const element = this.array.get(index) ?? 0
|
|
89
88
|
this.array.set(index, element | mask)
|
|
90
89
|
|
|
91
90
|
const added = (element & mask) !== mask
|
|
92
|
-
if (added)
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
if (added) this.#size++
|
|
92
|
+
|
|
93
|
+
if (value >= this.length) this.length = value + 1
|
|
94
|
+
|
|
95
95
|
return added
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -102,22 +102,24 @@ export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
|
|
|
102
102
|
this.array.set(index, element & ~mask)
|
|
103
103
|
|
|
104
104
|
const deleted = (element & mask) === mask
|
|
105
|
-
if (deleted)
|
|
106
|
-
|
|
107
|
-
}
|
|
105
|
+
if (deleted) this.#size--
|
|
106
|
+
|
|
108
107
|
return deleted
|
|
109
108
|
}
|
|
110
109
|
|
|
111
110
|
clear(): void {
|
|
112
|
-
this
|
|
111
|
+
this.#size = 0
|
|
112
|
+
this.length = 0
|
|
113
113
|
this.array.clear()
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
private getPosition(value: number): [index: number, mask: number] {
|
|
117
|
-
const remainder = value
|
|
118
|
-
const quotient =
|
|
117
|
+
const remainder = value & this.remainderMask
|
|
118
|
+
const quotient = value >>> this.quotientShift
|
|
119
|
+
|
|
119
120
|
const index = quotient
|
|
120
121
|
const mask = this.getMask(remainder)
|
|
122
|
+
|
|
121
123
|
return [index, mask]
|
|
122
124
|
}
|
|
123
125
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { UnsignedTypedArray } from 'justypes'
|
|
2
|
+
import { assert } from '@blackglory/errors'
|
|
3
|
+
import { trailingZeros } from '@utils/trailing-zeros.js'
|
|
4
|
+
|
|
5
|
+
export class TypedBitSet implements Iterable<number> {
|
|
6
|
+
private bitsPerElement: number
|
|
7
|
+
private length = 0
|
|
8
|
+
#size = 0
|
|
9
|
+
|
|
10
|
+
private quotientShift = 0
|
|
11
|
+
private remainderMask = 0
|
|
12
|
+
|
|
13
|
+
get [Symbol.toStringTag](): string {
|
|
14
|
+
return this.constructor.name
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get capacity(): number {
|
|
18
|
+
return this.array.length * this.bitsPerElement
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get size(): number {
|
|
22
|
+
return this.#size
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
constructor(private array: UnsignedTypedArray) {
|
|
26
|
+
const bitsPerElement = array.BYTES_PER_ELEMENT * 8
|
|
27
|
+
|
|
28
|
+
assert(
|
|
29
|
+
Number.isInteger(bitsPerElement)
|
|
30
|
+
, 'The bitsPerElement must be an integer'
|
|
31
|
+
)
|
|
32
|
+
assert(
|
|
33
|
+
bitsPerElement > 0
|
|
34
|
+
, 'The bitsPerElement must be greater than 0'
|
|
35
|
+
)
|
|
36
|
+
assert(
|
|
37
|
+
bitsPerElement <= 32
|
|
38
|
+
, 'The bitsPerElement must be less than or equal to 32'
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
this.bitsPerElement = bitsPerElement
|
|
42
|
+
this.quotientShift = Math.log2(bitsPerElement)
|
|
43
|
+
this.remainderMask = bitsPerElement - 1
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
47
|
+
return this.values()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
* values(): IterableIterator<number> {
|
|
51
|
+
if (this.length > 0) {
|
|
52
|
+
// maxArrayLength = Math.ceil(this.length / this.bitsPerElement)
|
|
53
|
+
const maxArrayLength = ~~(this.length / this.bitsPerElement) + 1
|
|
54
|
+
|
|
55
|
+
for (let index = 0; index < maxArrayLength; index++) {
|
|
56
|
+
let element = this.array[index] ?? 0
|
|
57
|
+
while (element !== 0) {
|
|
58
|
+
const indexOfBit = trailingZeros(element)
|
|
59
|
+
yield index * this.bitsPerElement + indexOfBit
|
|
60
|
+
// 移除最低位置的1, 以推进下一个indexOfBit的获取.
|
|
61
|
+
element &= element - 1
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
_dumpBinaryStrings(): string[] {
|
|
68
|
+
const result: string[] = []
|
|
69
|
+
for (let i = 0; i < this.array.length; i++) {
|
|
70
|
+
const binary = ((this.array[i] ?? 0) >>> 0).toString(2)
|
|
71
|
+
if (binary.length < this.bitsPerElement) {
|
|
72
|
+
result.push('0'.repeat(this.bitsPerElement - binary.length) + binary)
|
|
73
|
+
} else {
|
|
74
|
+
result.push(binary)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return result
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
has(value: number): boolean {
|
|
81
|
+
const [index, mask] = this.getPosition(value)
|
|
82
|
+
|
|
83
|
+
return (this.array[index] & mask) === mask
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
add(value: number): boolean {
|
|
87
|
+
const [index, mask] = this.getPosition(value)
|
|
88
|
+
assert(index < this.capacity, `The array is not large enough`)
|
|
89
|
+
|
|
90
|
+
const element = this.array[index]
|
|
91
|
+
this.array[index] = element | mask
|
|
92
|
+
|
|
93
|
+
const added = (element & mask) !== mask
|
|
94
|
+
if (added) this.#size++
|
|
95
|
+
|
|
96
|
+
if (value >= this.length) this.length = value + 1
|
|
97
|
+
|
|
98
|
+
return added
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
delete(value: number): boolean {
|
|
102
|
+
const [index, mask] = this.getPosition(value)
|
|
103
|
+
|
|
104
|
+
const element = this.array[index]
|
|
105
|
+
this.array[index] = element & ~mask
|
|
106
|
+
|
|
107
|
+
const deleted = (element & mask) === mask
|
|
108
|
+
if (deleted) this.#size--
|
|
109
|
+
|
|
110
|
+
return deleted
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
clear(): void {
|
|
114
|
+
this.#size = 0
|
|
115
|
+
this.length = 0
|
|
116
|
+
this.array.fill(0)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private getPosition(value: number): [index: number, mask: number] {
|
|
120
|
+
const remainder = value & this.remainderMask
|
|
121
|
+
const quotient = value >>> this.quotientShift
|
|
122
|
+
|
|
123
|
+
const index = quotient
|
|
124
|
+
const mask = this.getMask(remainder)
|
|
125
|
+
|
|
126
|
+
return [index, mask]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 输入一定是一个小于bitsPerElement的值, 取值范围是[0, bitsPerElement)
|
|
130
|
+
private getMask(value: number): number {
|
|
131
|
+
// return 2 ** value
|
|
132
|
+
return 1 << value
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
import { TypedArrayConstructor, TypedArrayOfConstructor } from 'justypes'
|
|
2
2
|
import { assert } from '@blackglory/errors'
|
|
3
|
+
import { computeNewCapacity } from '@utils/compute-new-capacity.js'
|
|
3
4
|
|
|
4
5
|
interface IDynamicTypedArrayOptions {
|
|
5
|
-
capacity?: number
|
|
6
6
|
growthFactor?: number
|
|
7
|
+
initialCapacity?: number
|
|
8
|
+
fillValue?: number
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
export class DynamicTypedArray<
|
|
12
|
+
T extends TypedArrayConstructor
|
|
13
|
+
> implements Iterable<number> {
|
|
11
14
|
private array: TypedArrayOfConstructor<T>
|
|
12
|
-
|
|
13
|
-
private initialCapacity: number
|
|
15
|
+
|
|
14
16
|
readonly growthFactor: number
|
|
17
|
+
readonly BYTES_PER_ELEMENT: number
|
|
18
|
+
readonly fillValue: number
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
return this.array
|
|
18
|
-
}
|
|
20
|
+
#length: number = 0
|
|
19
21
|
|
|
20
22
|
get [Symbol.toStringTag](): string {
|
|
21
23
|
return this.constructor.name
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
get
|
|
25
|
-
return this.
|
|
26
|
+
get internalTypedArray(): TypedArrayOfConstructor<T> {
|
|
27
|
+
return this.array
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
/**
|
|
@@ -36,23 +38,39 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
|
|
|
36
38
|
* 数组逻辑上的长度, 总是小于或等于capacity.
|
|
37
39
|
*/
|
|
38
40
|
get length(): number {
|
|
39
|
-
return this
|
|
41
|
+
return this.#length
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
constructor(
|
|
43
45
|
private typedArrayConstructor: T
|
|
44
46
|
, {
|
|
45
|
-
|
|
46
|
-
,
|
|
47
|
+
growthFactor = 1.5
|
|
48
|
+
, initialCapacity = 0
|
|
49
|
+
, fillValue = 0
|
|
47
50
|
}: IDynamicTypedArrayOptions = {}
|
|
48
51
|
) {
|
|
49
|
-
assert(Number.isInteger(capacity), 'capacity must be an integer')
|
|
50
|
-
assert(capacity >= 0, 'capacity must be greater than or equal to 0')
|
|
51
52
|
assert(growthFactor >= 1, 'growthFactory must be greater than or equal to 1')
|
|
53
|
+
assert(Number.isInteger(initialCapacity), 'initialCapacity must be an integer')
|
|
54
|
+
assert(initialCapacity >= 0, 'initialCapacity must be greater than or equal to 0')
|
|
52
55
|
|
|
53
|
-
this.initialCapacity = capacity
|
|
54
|
-
this.array = new typedArrayConstructor(capacity) as TypedArrayOfConstructor<T>
|
|
55
56
|
this.growthFactor = growthFactor
|
|
57
|
+
this.fillValue = fillValue
|
|
58
|
+
|
|
59
|
+
const array = new typedArrayConstructor(initialCapacity) as TypedArrayOfConstructor<T>
|
|
60
|
+
if (fillValue !== 0) array.fill(fillValue)
|
|
61
|
+
this.array = array
|
|
62
|
+
|
|
63
|
+
this.BYTES_PER_ELEMENT = typedArrayConstructor.BYTES_PER_ELEMENT
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
67
|
+
return this.values()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
* values(): IterableIterator<number> {
|
|
71
|
+
for (let i = 0; i < this.#length; i++) {
|
|
72
|
+
yield this.array[i]
|
|
73
|
+
}
|
|
56
74
|
}
|
|
57
75
|
|
|
58
76
|
set(index: number, value: number): void {
|
|
@@ -65,38 +83,39 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
|
|
|
65
83
|
this.resize(newCapacity)
|
|
66
84
|
}
|
|
67
85
|
|
|
68
|
-
if (index >= this
|
|
69
|
-
this
|
|
86
|
+
if (index >= this.#length) {
|
|
87
|
+
this.#length = index + 1
|
|
70
88
|
}
|
|
71
89
|
|
|
72
90
|
this.array[index] = value
|
|
73
91
|
}
|
|
74
92
|
|
|
75
|
-
setValues(index: number, values:
|
|
76
|
-
|
|
93
|
+
setValues(index: number, values: ArrayLike<number>): void {
|
|
94
|
+
const endIndex = index + values.length
|
|
95
|
+
if (endIndex > this.capacity) {
|
|
77
96
|
const newCapacity = computeNewCapacity(
|
|
78
97
|
this.capacity
|
|
79
|
-
,
|
|
98
|
+
, endIndex
|
|
80
99
|
, this.growthFactor
|
|
81
100
|
)
|
|
82
101
|
this.resize(newCapacity)
|
|
83
102
|
}
|
|
84
103
|
|
|
85
|
-
if (
|
|
86
|
-
this
|
|
104
|
+
if (endIndex > this.#length) {
|
|
105
|
+
this.#length = endIndex
|
|
87
106
|
}
|
|
88
107
|
|
|
89
|
-
this.
|
|
108
|
+
this.array.set(values, index)
|
|
90
109
|
}
|
|
91
110
|
|
|
92
111
|
get(index: number): number | undefined {
|
|
93
|
-
return index < this
|
|
112
|
+
return index < this.#length
|
|
94
113
|
? this.array[index]
|
|
95
114
|
: undefined
|
|
96
115
|
}
|
|
97
116
|
|
|
98
117
|
push(...values: number[]): void {
|
|
99
|
-
const newLength = this
|
|
118
|
+
const newLength = this.#length + values.length
|
|
100
119
|
if (newLength > this.capacity) {
|
|
101
120
|
const newCapacity = computeNewCapacity(
|
|
102
121
|
this.capacity
|
|
@@ -107,21 +126,14 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
|
|
|
107
126
|
}
|
|
108
127
|
|
|
109
128
|
for (const value of values) {
|
|
110
|
-
this.array[this
|
|
129
|
+
this.array[this.#length++] = value
|
|
111
130
|
}
|
|
112
131
|
}
|
|
113
132
|
|
|
114
133
|
pop(): number | undefined {
|
|
115
|
-
if (this
|
|
116
|
-
const value = this.array[this
|
|
117
|
-
this
|
|
118
|
-
|
|
119
|
-
const newCapacity = computeNewCapacity(
|
|
120
|
-
this.capacity
|
|
121
|
-
, this.length
|
|
122
|
-
, this.growthFactor
|
|
123
|
-
)
|
|
124
|
-
this.resize(newCapacity)
|
|
134
|
+
if (this.#length > 0) {
|
|
135
|
+
const value = this.array[this.#length - 1]
|
|
136
|
+
this.#length--
|
|
125
137
|
|
|
126
138
|
return value
|
|
127
139
|
} else {
|
|
@@ -130,9 +142,16 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
|
|
|
130
142
|
}
|
|
131
143
|
|
|
132
144
|
clear(): void {
|
|
133
|
-
this
|
|
134
|
-
|
|
135
|
-
|
|
145
|
+
this.#length = 0
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
shrink(): void {
|
|
149
|
+
const newCapacity = computeNewCapacity(
|
|
150
|
+
this.capacity
|
|
151
|
+
, this.length
|
|
152
|
+
, this.growthFactor
|
|
153
|
+
)
|
|
154
|
+
this.resize(newCapacity)
|
|
136
155
|
}
|
|
137
156
|
|
|
138
157
|
sort(compare?: (a: number, b: number) => number): void {
|
|
@@ -148,8 +167,14 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
|
|
|
148
167
|
} else if (this.array.length < newCapacity) {
|
|
149
168
|
const newArray = new this.typedArrayConstructor(newCapacity)
|
|
150
169
|
newArray.set(this.array)
|
|
170
|
+
|
|
171
|
+
if (this.fillValue !== 0) {
|
|
172
|
+
const startIndex = this.array.length
|
|
173
|
+
newArray.fill(this.fillValue, startIndex)
|
|
174
|
+
}
|
|
175
|
+
|
|
151
176
|
this.array = newArray as TypedArrayOfConstructor<T>
|
|
152
|
-
} else if (this.array.length > newCapacity) {
|
|
177
|
+
} else /* if (this.array.length > newCapacity) */ {
|
|
153
178
|
const newArray = new this.typedArrayConstructor(newCapacity)
|
|
154
179
|
// 不需要的部分将被舍弃.
|
|
155
180
|
for (let i = newCapacity; i--;) {
|
|
@@ -159,43 +184,3 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
|
|
|
159
184
|
}
|
|
160
185
|
}
|
|
161
186
|
}
|
|
162
|
-
|
|
163
|
-
export function computeNewCapacity(
|
|
164
|
-
oldCapacity: number
|
|
165
|
-
, targetLength: number
|
|
166
|
-
, growthFactor: number
|
|
167
|
-
): number {
|
|
168
|
-
if (growthFactor === 1) {
|
|
169
|
-
return targetLength
|
|
170
|
-
} else {
|
|
171
|
-
if (oldCapacity === targetLength) {
|
|
172
|
-
return targetLength
|
|
173
|
-
} else if (oldCapacity < targetLength) {
|
|
174
|
-
// 增加容量以适配targetLength
|
|
175
|
-
let newCapacity = Math.max(oldCapacity, 1)
|
|
176
|
-
while (newCapacity < targetLength) {
|
|
177
|
-
newCapacity *= growthFactor
|
|
178
|
-
}
|
|
179
|
-
return Math.floor(newCapacity)
|
|
180
|
-
} else {
|
|
181
|
-
// 尝试减少容量以适配targetLength
|
|
182
|
-
|
|
183
|
-
// `targetLength = 0`是特殊情况,
|
|
184
|
-
// 此时无论怎么将oldCapacity除以growthFactory几次, 都不可能得到比targetLength小的结果.
|
|
185
|
-
if (targetLength === 0) {
|
|
186
|
-
return 0
|
|
187
|
-
} else {
|
|
188
|
-
let newCapacity = oldCapacity
|
|
189
|
-
while (true) {
|
|
190
|
-
const temp = newCapacity / growthFactor
|
|
191
|
-
if (temp < targetLength) {
|
|
192
|
-
break
|
|
193
|
-
} else {
|
|
194
|
-
newCapacity = temp
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return Math.floor(newCapacity)
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -17,12 +17,10 @@ export * from './trie-map.js'
|
|
|
17
17
|
export * from './string-trie-map.js'
|
|
18
18
|
export { RadixTree } from './radix-tree.js'
|
|
19
19
|
export { StringRadixTree } from './string-radix-tree.js'
|
|
20
|
-
export * from './
|
|
21
|
-
export * from './
|
|
22
|
-
export * from './typed-sparse-map.js'
|
|
23
|
-
export * from './typed-sparse-set.js'
|
|
24
|
-
export { DynamicTypedArray } from './dynamic-typed-array.js'
|
|
20
|
+
export * from './dynamic-typed-array.js'
|
|
21
|
+
export * from './resizable-typed-array.js'
|
|
25
22
|
export * from './sorted-set.js'
|
|
26
|
-
export * from './bit-set.js'
|
|
27
|
-
export * from './typed-bit-set.js'
|
|
28
23
|
export * from './disjoint-set.js'
|
|
24
|
+
export * from './bit-set/index.js'
|
|
25
|
+
export * from './sparse-set/index.js'
|
|
26
|
+
export * from './sparse-map/index.js'
|
package/src/radix-tree.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { toArray, first, map, find } from 'iterable-operator'
|
|
2
|
-
import { isntUndefined } from 'extra-utils'
|
|
2
|
+
import { isntUndefined, isUndefined } from 'extra-utils'
|
|
3
3
|
|
|
4
4
|
class TreeNode<T, U> {
|
|
5
5
|
children = new Map<T[], TreeNode<T, U>>()
|
|
6
6
|
|
|
7
|
-
constructor(public value
|
|
7
|
+
constructor(public value: U | undefined = undefined) {}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export class RadixTree<K extends Iterable<T>, V, T = unknown> {
|
|
@@ -146,7 +146,7 @@ export class RadixTree<K extends Iterable<T>, V, T = unknown> {
|
|
|
146
146
|
const deleted = _delete(nextKey, nextNode)
|
|
147
147
|
if (deleted) {
|
|
148
148
|
// 最终找到了目标节点并删除了它, 现在执行与nextNode有关的合并操作, 以删除不必要的节点.
|
|
149
|
-
if (
|
|
149
|
+
if (isUndefined(nextNode.value)) {
|
|
150
150
|
// 只有在nextNode自身不具有值的情况下, nextNode才是能够被合并的.
|
|
151
151
|
switch (nextNode.children.size) {
|
|
152
152
|
case 0: {
|