@quenty/observablecollection 12.20.0 → 12.20.1
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/CHANGELOG.md +11 -0
- package/package.json +15 -15
- package/src/Shared/ObservableCountingMap.lua +102 -81
- package/src/Shared/ObservableList.lua +91 -70
- package/src/Shared/ObservableMap.lua +100 -78
- package/src/Shared/ObservableMapList.lua +2 -2
- package/src/Shared/ObservableMapSet.lua +83 -41
- package/src/Shared/ObservableSet.lua +61 -34
- package/src/Shared/SortedList/ObservableSortedList.lua +128 -58
- package/src/Shared/SortedList/ObservableSortedList.story.lua +1 -1
- package/src/Shared/SortedList/SortFunctionUtils.lua +25 -8
- package/src/Shared/SortedList/SortedNode.lua +231 -116
- package/src/Shared/SortedList/SortedNodeValue.lua +17 -6
- package/src/Shared/Utils/ListIndexUtils.lua +9 -2
- package/test/scripts/Server/ServerMain.server.lua +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
Used by [ObservableSortedList] to maintain a red-black binary search tree.
|
|
3
4
|
|
|
@@ -9,31 +10,44 @@ local require = require(script.Parent.loader).load(script)
|
|
|
9
10
|
local ListIndexUtils = require("ListIndexUtils")
|
|
10
11
|
local DuckTypeUtils = require("DuckTypeUtils")
|
|
11
12
|
local Table = require("Table")
|
|
13
|
+
local SortedNodeValue = require("SortedNodeValue")
|
|
14
|
+
local _SortFunctionUtils = require("SortFunctionUtils")
|
|
12
15
|
|
|
13
16
|
local DEBUG_ASSERTION_SLOW = false
|
|
14
17
|
|
|
18
|
+
export type SortedNodeColor = "BLACK" | "RED"
|
|
19
|
+
|
|
20
|
+
export type SortedNodeColorMap = {
|
|
21
|
+
BLACK: "BLACK",
|
|
22
|
+
RED: "RED",
|
|
23
|
+
}
|
|
24
|
+
|
|
15
25
|
local Color = Table.readonly({
|
|
16
|
-
BLACK = "BLACK"
|
|
17
|
-
RED = "RED"
|
|
18
|
-
})
|
|
26
|
+
BLACK = "BLACK",
|
|
27
|
+
RED = "RED",
|
|
28
|
+
} :: SortedNodeColorMap)
|
|
19
29
|
|
|
20
30
|
local SortedNode = {}
|
|
21
31
|
SortedNode.ClassName = "SortedNode"
|
|
22
32
|
SortedNode.__index = SortedNode
|
|
23
33
|
|
|
24
|
-
export type SortedNode<T> = typeof(setmetatable(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
export type SortedNode<T> = typeof(setmetatable(
|
|
35
|
+
{} :: {
|
|
36
|
+
left: SortedNode<T>?,
|
|
37
|
+
right: SortedNode<T>?,
|
|
38
|
+
parent: SortedNode<T>?,
|
|
39
|
+
color: SortedNodeColor,
|
|
40
|
+
value: number?, -- Actually SortedNodeValue too, but we treat as number
|
|
41
|
+
descendantCount: number,
|
|
42
|
+
data: T,
|
|
43
|
+
},
|
|
44
|
+
SortedNode
|
|
45
|
+
))
|
|
46
|
+
|
|
47
|
+
function SortedNode.new<T>(data: T): SortedNode<T>
|
|
34
48
|
assert(data ~= nil, "Bad data")
|
|
35
49
|
|
|
36
|
-
local self = setmetatable({}, SortedNode)
|
|
50
|
+
local self: SortedNode<T> = setmetatable({} :: any, SortedNode)
|
|
37
51
|
|
|
38
52
|
self.data = data
|
|
39
53
|
self.color = Color.RED
|
|
@@ -42,14 +56,14 @@ function SortedNode.new(data): SortedNode<T>
|
|
|
42
56
|
return self
|
|
43
57
|
end
|
|
44
58
|
|
|
45
|
-
function SortedNode.isSortedNode(value)
|
|
59
|
+
function SortedNode.isSortedNode(value: any): boolean
|
|
46
60
|
return DuckTypeUtils.isImplementation(SortedNode, value)
|
|
47
61
|
end
|
|
48
62
|
|
|
49
|
-
function SortedNode
|
|
63
|
+
function SortedNode.IterateNodes<T>(self: SortedNode<T>): _SortFunctionUtils.WrappedIterator<number, SortedNode<T>>
|
|
50
64
|
return coroutine.wrap(function()
|
|
51
|
-
local stack = {}
|
|
52
|
-
local current = self
|
|
65
|
+
local stack: { SortedNode<T> } = {}
|
|
66
|
+
local current: any? = self
|
|
53
67
|
local index = 1
|
|
54
68
|
|
|
55
69
|
while current or #stack > 0 do
|
|
@@ -62,15 +76,15 @@ function SortedNode:IterateNodes()
|
|
|
62
76
|
current = table.remove(stack)
|
|
63
77
|
coroutine.yield(index, current)
|
|
64
78
|
index += 1
|
|
65
|
-
current = current.right
|
|
79
|
+
current = (current :: any).right
|
|
66
80
|
end
|
|
67
|
-
end)
|
|
81
|
+
end) :: any
|
|
68
82
|
end
|
|
69
83
|
|
|
70
|
-
function SortedNode
|
|
84
|
+
function SortedNode.IterateData<T>(self: SortedNode<T>): _SortFunctionUtils.WrappedIterator<number, T>
|
|
71
85
|
return coroutine.wrap(function()
|
|
72
|
-
local stack = {}
|
|
73
|
-
local current = self
|
|
86
|
+
local stack: { SortedNode<T> } = {}
|
|
87
|
+
local current: any = self
|
|
74
88
|
local index = 1
|
|
75
89
|
|
|
76
90
|
while current or #stack > 0 do
|
|
@@ -80,12 +94,12 @@ function SortedNode:IterateData()
|
|
|
80
94
|
current = current.left
|
|
81
95
|
end
|
|
82
96
|
|
|
83
|
-
|
|
84
|
-
coroutine.yield(index,
|
|
97
|
+
local removed: SortedNode<T> = assert(table.remove(stack), "Must have entry")
|
|
98
|
+
coroutine.yield(index, removed.data)
|
|
85
99
|
index += 1
|
|
86
|
-
current =
|
|
100
|
+
current = removed.right
|
|
87
101
|
end
|
|
88
|
-
end)
|
|
102
|
+
end) :: any
|
|
89
103
|
end
|
|
90
104
|
|
|
91
105
|
--[=[
|
|
@@ -96,7 +110,11 @@ end
|
|
|
96
110
|
@param finish number
|
|
97
111
|
@return (T) -> ((T, nextIndex: any) -> ...any, T?)
|
|
98
112
|
]=]
|
|
99
|
-
function SortedNode
|
|
113
|
+
function SortedNode.IterateNodesRange<T>(
|
|
114
|
+
self: SortedNode<T>,
|
|
115
|
+
start: number,
|
|
116
|
+
finish: number
|
|
117
|
+
): _SortFunctionUtils.WrappedIterator<number, SortedNode<T>>
|
|
100
118
|
assert(type(start) == "number", "Bad start")
|
|
101
119
|
assert(type(finish) == "number" or finish == nil, "Bad finish")
|
|
102
120
|
assert(self.parent == nil, "Should only be called on root")
|
|
@@ -106,16 +124,16 @@ function SortedNode:IterateNodesRange(start, finish)
|
|
|
106
124
|
end
|
|
107
125
|
|
|
108
126
|
return coroutine.wrap(function()
|
|
109
|
-
local target = ListIndexUtils.toPositiveIndex(self.descendantCount, start)
|
|
110
|
-
local endTarget = ListIndexUtils.toPositiveIndex(self.descendantCount, finish or -1)
|
|
111
|
-
local current = self:FindNodeAtIndex(target)
|
|
127
|
+
local target: number = ListIndexUtils.toPositiveIndex(self.descendantCount, start)
|
|
128
|
+
local endTarget: number = ListIndexUtils.toPositiveIndex(self.descendantCount, finish or -1)
|
|
129
|
+
local current: any? = self:FindNodeAtIndex(target)
|
|
112
130
|
|
|
113
131
|
-- We're out of range
|
|
114
132
|
if not current then
|
|
115
133
|
return
|
|
116
134
|
end
|
|
117
135
|
|
|
118
|
-
local index = target
|
|
136
|
+
local index: number = target
|
|
119
137
|
|
|
120
138
|
while current do
|
|
121
139
|
coroutine.yield(index, current)
|
|
@@ -144,10 +162,12 @@ function SortedNode:IterateNodesRange(start, finish)
|
|
|
144
162
|
|
|
145
163
|
current = current.parent
|
|
146
164
|
end
|
|
147
|
-
|
|
165
|
+
|
|
166
|
+
return
|
|
167
|
+
end) :: any
|
|
148
168
|
end
|
|
149
169
|
|
|
150
|
-
function SortedNode
|
|
170
|
+
function SortedNode.FindNodeAtIndex<T>(self: SortedNode<T>, searchIndex: number): SortedNode<T>?
|
|
151
171
|
assert(type(searchIndex) == "number", "Bad searchIndex")
|
|
152
172
|
assert(self.parent == nil, "Should only be called on root")
|
|
153
173
|
|
|
@@ -156,7 +176,7 @@ function SortedNode:FindNodeAtIndex(searchIndex)
|
|
|
156
176
|
return nil
|
|
157
177
|
end
|
|
158
178
|
|
|
159
|
-
local current = self
|
|
179
|
+
local current: any = self
|
|
160
180
|
local index = 1
|
|
161
181
|
if self.left then
|
|
162
182
|
index += self.left.descendantCount
|
|
@@ -183,7 +203,7 @@ function SortedNode:FindNodeAtIndex(searchIndex)
|
|
|
183
203
|
return nil
|
|
184
204
|
end
|
|
185
205
|
|
|
186
|
-
function SortedNode
|
|
206
|
+
function SortedNode.FindNodeIndex<T>(self: SortedNode<T>, node: SortedNode<T>): number?
|
|
187
207
|
assert(SortedNode.isSortedNode(node), "Bad node")
|
|
188
208
|
assert(self.parent == nil, "Should only be called on root")
|
|
189
209
|
|
|
@@ -195,7 +215,7 @@ function SortedNode:FindNodeIndex(node)
|
|
|
195
215
|
end
|
|
196
216
|
end
|
|
197
217
|
|
|
198
|
-
function SortedNode
|
|
218
|
+
function SortedNode.GetIndex<T>(self: SortedNode<T>): number
|
|
199
219
|
local index = 1
|
|
200
220
|
|
|
201
221
|
if self.left then
|
|
@@ -207,8 +227,8 @@ function SortedNode:GetIndex(): number
|
|
|
207
227
|
if current == current.parent.right then
|
|
208
228
|
index += 1
|
|
209
229
|
|
|
210
|
-
if current.parent.left then
|
|
211
|
-
index += current.parent.left.descendantCount
|
|
230
|
+
if (current :: any).parent.left then
|
|
231
|
+
index += (current :: any).parent.left.descendantCount
|
|
212
232
|
end
|
|
213
233
|
end
|
|
214
234
|
|
|
@@ -218,7 +238,7 @@ function SortedNode:GetIndex(): number
|
|
|
218
238
|
return index
|
|
219
239
|
end
|
|
220
240
|
|
|
221
|
-
function SortedNode
|
|
241
|
+
function SortedNode.FindFirstNodeForData<T>(self: SortedNode<T>, data: T): SortedNode<T>?
|
|
222
242
|
-- TODO: This is a linear search, very bad
|
|
223
243
|
|
|
224
244
|
for _, current in self:IterateNodes() do
|
|
@@ -230,7 +250,7 @@ function SortedNode:FindFirstNodeForData(data)
|
|
|
230
250
|
return nil
|
|
231
251
|
end
|
|
232
252
|
|
|
233
|
-
function SortedNode
|
|
253
|
+
function SortedNode.NeedsToMove<T>(self: SortedNode<T>, root: SortedNode<T>?, newValue: number): boolean
|
|
234
254
|
assert(newValue ~= nil, "Bad newValue")
|
|
235
255
|
|
|
236
256
|
if self.parent ~= nil then
|
|
@@ -263,10 +283,10 @@ end
|
|
|
263
283
|
--[=[
|
|
264
284
|
Returns true if the node is contained within the parent node
|
|
265
285
|
]=]
|
|
266
|
-
function SortedNode
|
|
286
|
+
function SortedNode.ContainsNode<T>(self: SortedNode<T>, node: SortedNode<T>): boolean
|
|
267
287
|
assert(SortedNode.isSortedNode(node), "Bad SortedNode")
|
|
268
288
|
|
|
269
|
-
local current = node
|
|
289
|
+
local current: any = node
|
|
270
290
|
while current do
|
|
271
291
|
if current == self then
|
|
272
292
|
return true
|
|
@@ -278,11 +298,11 @@ function SortedNode:ContainsNode(node: SortedNode): boolean
|
|
|
278
298
|
return false
|
|
279
299
|
end
|
|
280
300
|
|
|
281
|
-
function SortedNode
|
|
301
|
+
function SortedNode.MarkBlack<T>(self: SortedNode<T>)
|
|
282
302
|
self.color = Color.BLACK
|
|
283
303
|
end
|
|
284
304
|
|
|
285
|
-
function SortedNode
|
|
305
|
+
function SortedNode.InsertNode<T>(self: SortedNode<T>, node: SortedNode<T>): SortedNode<T>
|
|
286
306
|
assert(SortedNode.isSortedNode(node), "Bad SortedNode")
|
|
287
307
|
assert(self.parent == nil, "Should only be called on root")
|
|
288
308
|
assert(node.parent == nil, "Already parented")
|
|
@@ -294,8 +314,8 @@ function SortedNode:InsertNode(node): SortedNode<T>
|
|
|
294
314
|
|
|
295
315
|
node.color = Color.RED
|
|
296
316
|
|
|
297
|
-
local parent = nil
|
|
298
|
-
local current = root
|
|
317
|
+
local parent: SortedNode<T>? = nil
|
|
318
|
+
local current: any = root
|
|
299
319
|
|
|
300
320
|
while current ~= nil do
|
|
301
321
|
parent = current
|
|
@@ -329,7 +349,7 @@ function SortedNode:InsertNode(node): SortedNode<T>
|
|
|
329
349
|
return root
|
|
330
350
|
end
|
|
331
351
|
|
|
332
|
-
function SortedNode
|
|
352
|
+
function SortedNode._leftRotate<T>(_self: SortedNode<T>, root, node): SortedNode<T>
|
|
333
353
|
assert(root, "No root")
|
|
334
354
|
assert(node, "No node")
|
|
335
355
|
|
|
@@ -352,7 +372,7 @@ function SortedNode:_leftRotate(root, node): SortedNode<T>
|
|
|
352
372
|
return root
|
|
353
373
|
end
|
|
354
374
|
|
|
355
|
-
function SortedNode
|
|
375
|
+
function SortedNode._rightRotate<T>(_self: SortedNode<T>, root, node): SortedNode<T>
|
|
356
376
|
assert(root, "No root")
|
|
357
377
|
assert(node, "No node")
|
|
358
378
|
|
|
@@ -375,19 +395,19 @@ function SortedNode:_rightRotate(root, node): SortedNode<T>
|
|
|
375
395
|
return root
|
|
376
396
|
end
|
|
377
397
|
|
|
378
|
-
function SortedNode
|
|
398
|
+
function SortedNode._swapColors<T>(self: SortedNode<T>, other: SortedNode<T>)
|
|
379
399
|
self.color, other.color = other.color, self.color
|
|
380
400
|
end
|
|
381
401
|
|
|
382
|
-
function SortedNode
|
|
402
|
+
function SortedNode._fixDoubleRed<T>(self: SortedNode<T>, root: SortedNode<T>, node: SortedNode<T>): SortedNode<T>
|
|
383
403
|
if node == root then
|
|
384
404
|
node.color = Color.BLACK
|
|
385
405
|
return root
|
|
386
406
|
end
|
|
387
407
|
|
|
388
|
-
local parent = node.parent
|
|
389
|
-
local grandparent = node.parent and node.parent.parent
|
|
390
|
-
local uncle = node:_uncle()
|
|
408
|
+
local parent: any = assert(node.parent, "Must have node parent")
|
|
409
|
+
local grandparent: any = node.parent and node.parent.parent
|
|
410
|
+
local uncle: any = node:_uncle()
|
|
391
411
|
|
|
392
412
|
if not grandparent then
|
|
393
413
|
return root
|
|
@@ -435,7 +455,7 @@ function SortedNode:_fixDoubleRed(root, node): SortedNode
|
|
|
435
455
|
return root
|
|
436
456
|
end
|
|
437
457
|
|
|
438
|
-
function SortedNode
|
|
458
|
+
function SortedNode._setLeft<T>(self: SortedNode<T>, node: SortedNode<T>?)
|
|
439
459
|
assert(node ~= self, "Cannot assign to self")
|
|
440
460
|
|
|
441
461
|
if self.left == node then
|
|
@@ -453,20 +473,19 @@ function SortedNode:_setLeft(node: SortedNode)
|
|
|
453
473
|
end
|
|
454
474
|
|
|
455
475
|
self.left = node
|
|
456
|
-
|
|
476
|
+
node.parent = self
|
|
457
477
|
end
|
|
458
478
|
|
|
459
479
|
self:_updateAllParentDescendantCount()
|
|
460
480
|
end
|
|
461
481
|
|
|
462
|
-
function SortedNode
|
|
482
|
+
function SortedNode._setRight<T>(self: SortedNode<T>, node: SortedNode<T>?)
|
|
463
483
|
assert(node ~= self, "Cannot assign to self")
|
|
464
484
|
|
|
465
485
|
if self.right == node then
|
|
466
486
|
return
|
|
467
487
|
end
|
|
468
488
|
|
|
469
|
-
|
|
470
489
|
if self.right then
|
|
471
490
|
self.right.parent = nil
|
|
472
491
|
self.right = nil
|
|
@@ -478,14 +497,14 @@ function SortedNode:_setRight(node: SortedNode)
|
|
|
478
497
|
end
|
|
479
498
|
|
|
480
499
|
self.right = node
|
|
481
|
-
|
|
500
|
+
node.parent = self
|
|
482
501
|
end
|
|
483
502
|
|
|
484
503
|
self:_updateAllParentDescendantCount()
|
|
485
504
|
end
|
|
486
505
|
|
|
487
|
-
function SortedNode
|
|
488
|
-
local current = self
|
|
506
|
+
function SortedNode._updateAllParentDescendantCount<T>(self: SortedNode<T>)
|
|
507
|
+
local current: any = self
|
|
489
508
|
while current do
|
|
490
509
|
local descendantCount = 1
|
|
491
510
|
local left = current.left
|
|
@@ -502,7 +521,7 @@ function SortedNode:_updateAllParentDescendantCount()
|
|
|
502
521
|
end
|
|
503
522
|
end
|
|
504
523
|
|
|
505
|
-
function SortedNode
|
|
524
|
+
function SortedNode.RemoveNode<T>(self: SortedNode<T>, node: SortedNode<T>): SortedNode<T>
|
|
506
525
|
assert(SortedNode.isSortedNode(node), "Bad SortedNode")
|
|
507
526
|
assert(self.parent == nil, "Should only be called on root")
|
|
508
527
|
|
|
@@ -534,7 +553,12 @@ function SortedNode:RemoveNode(node: SortedNode): SortedNode
|
|
|
534
553
|
return root
|
|
535
554
|
end
|
|
536
555
|
|
|
537
|
-
function SortedNode
|
|
556
|
+
function SortedNode._removeNodeHelper<T>(
|
|
557
|
+
self: SortedNode<T>,
|
|
558
|
+
root: SortedNode<T>?,
|
|
559
|
+
node: SortedNode<T>?,
|
|
560
|
+
depth: number?
|
|
561
|
+
): SortedNode<T>
|
|
538
562
|
assert(root, "Bad root")
|
|
539
563
|
assert(node, "Bad node")
|
|
540
564
|
depth = (depth or 0) + 1
|
|
@@ -572,7 +596,7 @@ function SortedNode:_removeNodeHelper(root, node, depth)
|
|
|
572
596
|
root = self:_swapNodes(root, node, replacement)
|
|
573
597
|
root = self:_removeNodeHelper(root, node, depth)
|
|
574
598
|
else
|
|
575
|
-
assert(
|
|
599
|
+
assert(parent, "Node must have parent")
|
|
576
600
|
|
|
577
601
|
if node:_isOnLeft() then
|
|
578
602
|
parent:_setLeft(replacement)
|
|
@@ -609,7 +633,12 @@ function SortedNode:_removeNodeHelper(root, node, depth)
|
|
|
609
633
|
return root
|
|
610
634
|
end
|
|
611
635
|
|
|
612
|
-
function SortedNode
|
|
636
|
+
function SortedNode._swapNodes<T>(
|
|
637
|
+
_self: SortedNode<T>,
|
|
638
|
+
root: SortedNode<T>,
|
|
639
|
+
node: SortedNode<T>,
|
|
640
|
+
replacement: SortedNode<T>
|
|
641
|
+
): SortedNode<T>?
|
|
613
642
|
assert(root, "No root")
|
|
614
643
|
assert(node, "No node")
|
|
615
644
|
assert(replacement, "No replacement")
|
|
@@ -628,12 +657,12 @@ function SortedNode:_swapNodes(root, node, replacement)
|
|
|
628
657
|
local nodeLeft = node.left
|
|
629
658
|
local nodeRight = node.right
|
|
630
659
|
local nodeOnLeft = nodeParent and node:_isOnLeft()
|
|
631
|
-
local nodeColor = node.color
|
|
660
|
+
local nodeColor: SortedNodeColor = node.color
|
|
632
661
|
local replacementLeft = replacement.left
|
|
633
662
|
local replacementRight = replacement.right
|
|
634
663
|
local replacementParent = replacement.parent
|
|
635
664
|
local replacementOnLeft = replacement:_isOnLeft()
|
|
636
|
-
local replacementColor = replacement.color
|
|
665
|
+
local replacementColor: SortedNodeColor = replacement.color
|
|
637
666
|
|
|
638
667
|
if replacement.parent == node then
|
|
639
668
|
node:_unparent()
|
|
@@ -718,7 +747,7 @@ function SortedNode:_swapNodes(root, node, replacement)
|
|
|
718
747
|
return root
|
|
719
748
|
end
|
|
720
749
|
|
|
721
|
-
function SortedNode
|
|
750
|
+
function SortedNode._findReplacement<T>(_self: SortedNode<T>, node: SortedNode<T>): SortedNode<T>?
|
|
722
751
|
if node.left and node.right then
|
|
723
752
|
return node.right:_successor()
|
|
724
753
|
end
|
|
@@ -734,7 +763,7 @@ function SortedNode:_findReplacement(node)
|
|
|
734
763
|
end
|
|
735
764
|
end
|
|
736
765
|
|
|
737
|
-
function SortedNode
|
|
766
|
+
function SortedNode._successor<T>(self: SortedNode<T>): SortedNode<T>
|
|
738
767
|
local node = self
|
|
739
768
|
while node.left ~= nil do
|
|
740
769
|
node = node.left
|
|
@@ -745,7 +774,7 @@ end
|
|
|
745
774
|
--[[
|
|
746
775
|
https://www.geeksforgeeks.org/deletion-in-red-black-tree/?ref=oin_asr9
|
|
747
776
|
]]
|
|
748
|
-
function SortedNode
|
|
777
|
+
function SortedNode._fixDoubleBlack<T>(self: SortedNode<T>, root: SortedNode<T>, node: SortedNode<T>): SortedNode<T>
|
|
749
778
|
assert(root, "No root")
|
|
750
779
|
assert(node, "No node")
|
|
751
780
|
|
|
@@ -798,13 +827,13 @@ function SortedNode:_fixDoubleBlack(root, node)
|
|
|
798
827
|
else
|
|
799
828
|
if sibling:_isOnLeft() then
|
|
800
829
|
-- Left-right
|
|
801
|
-
sibling.right.color = parent.color
|
|
830
|
+
(sibling :: any).right.color = parent.color
|
|
802
831
|
parent.color = Color.BLACK -- This should be true, but the guide I'm following doesn't specify this?
|
|
803
832
|
root = self:_leftRotate(root, sibling)
|
|
804
833
|
root = self:_rightRotate(root, parent)
|
|
805
834
|
else
|
|
806
835
|
-- Right-right
|
|
807
|
-
sibling.right.color = sibling.color
|
|
836
|
+
(sibling :: any).right.color = sibling.color
|
|
808
837
|
sibling.color = parent.color
|
|
809
838
|
parent.color = Color.BLACK -- This should be true, but the guide I'm following doesn't specify this?
|
|
810
839
|
root = self:_leftRotate(root, parent)
|
|
@@ -826,19 +855,19 @@ function SortedNode:_fixDoubleBlack(root, node)
|
|
|
826
855
|
return root
|
|
827
856
|
end
|
|
828
857
|
|
|
829
|
-
function SortedNode
|
|
858
|
+
function SortedNode._isOnLeft<T>(self: SortedNode<T>): boolean
|
|
830
859
|
assert(self.parent, "Must have parent to invoke this method")
|
|
831
860
|
|
|
832
861
|
return self.parent.left == self
|
|
833
862
|
end
|
|
834
863
|
|
|
835
|
-
function SortedNode
|
|
864
|
+
function SortedNode._isOnRight<T>(self: SortedNode<T>): boolean
|
|
836
865
|
assert(self.parent, "Must have parent to invoke this method")
|
|
837
866
|
|
|
838
867
|
return self.parent.right == self
|
|
839
868
|
end
|
|
840
869
|
|
|
841
|
-
function SortedNode
|
|
870
|
+
function SortedNode._hasRedChild<T>(self: SortedNode<T>): boolean
|
|
842
871
|
if self.left and self.left.color == Color.RED then
|
|
843
872
|
return true
|
|
844
873
|
end
|
|
@@ -850,20 +879,20 @@ function SortedNode:_hasRedChild()
|
|
|
850
879
|
return false
|
|
851
880
|
end
|
|
852
881
|
|
|
853
|
-
function SortedNode
|
|
854
|
-
|
|
882
|
+
function SortedNode._unparent<T>(self: SortedNode<T>)
|
|
883
|
+
local parent = self.parent
|
|
884
|
+
if not parent then
|
|
855
885
|
return
|
|
856
|
-
elseif
|
|
857
|
-
|
|
858
|
-
elseif
|
|
859
|
-
|
|
886
|
+
elseif parent.left == self then
|
|
887
|
+
parent:_setLeft(nil)
|
|
888
|
+
elseif parent.right == self then
|
|
889
|
+
parent:_setRight(nil)
|
|
860
890
|
else
|
|
861
891
|
error("Bad state")
|
|
862
892
|
end
|
|
863
893
|
end
|
|
864
894
|
|
|
865
|
-
|
|
866
|
-
function SortedNode:_uncle()
|
|
895
|
+
function SortedNode._uncle<T>(self: SortedNode<T>): SortedNode<T>?
|
|
867
896
|
local grandparent = self:_grandparent()
|
|
868
897
|
if not grandparent then
|
|
869
898
|
return nil
|
|
@@ -878,12 +907,13 @@ function SortedNode:_uncle()
|
|
|
878
907
|
end
|
|
879
908
|
end
|
|
880
909
|
|
|
881
|
-
function SortedNode
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
910
|
+
function SortedNode._sibling<T>(self: SortedNode<T>): SortedNode<T>?
|
|
911
|
+
local parent = self.parent
|
|
912
|
+
if parent then
|
|
913
|
+
if self == parent.left then
|
|
914
|
+
return parent.right
|
|
915
|
+
elseif self == parent.right then
|
|
916
|
+
return parent.left
|
|
887
917
|
else
|
|
888
918
|
error("Bad state")
|
|
889
919
|
end
|
|
@@ -892,7 +922,7 @@ function SortedNode:_sibling()
|
|
|
892
922
|
end
|
|
893
923
|
end
|
|
894
924
|
|
|
895
|
-
function SortedNode
|
|
925
|
+
function SortedNode._grandparent<T>(self: SortedNode<T>)
|
|
896
926
|
if self.parent then
|
|
897
927
|
return self.parent.parent
|
|
898
928
|
else
|
|
@@ -900,20 +930,26 @@ function SortedNode:_grandparent()
|
|
|
900
930
|
end
|
|
901
931
|
end
|
|
902
932
|
|
|
903
|
-
|
|
904
|
-
|
|
933
|
+
type SortedNodeTostringStackEntry<T> = {
|
|
934
|
+
node: SortedNode<T>?,
|
|
935
|
+
indent: string,
|
|
936
|
+
isLeft: boolean,
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
function SortedNode.__tostring<T>(self: SortedNode<T>): string
|
|
940
|
+
local result: string
|
|
905
941
|
if self.parent == nil then
|
|
906
942
|
result = "BinarySearchTree\n"
|
|
907
943
|
else
|
|
908
944
|
result = "SortedNode\n"
|
|
909
945
|
end
|
|
910
946
|
|
|
911
|
-
local stack = {} -- Stack to hold nodes and their details
|
|
947
|
+
local stack: { SortedNodeTostringStackEntry<T> } = {} -- Stack to hold nodes and their details
|
|
912
948
|
local seen = {}
|
|
913
949
|
table.insert(stack, { node = self, indent = "", isLeft = false })
|
|
914
950
|
|
|
915
951
|
while #stack > 0 do
|
|
916
|
-
local current = table.remove(stack) -- Pop from the stack
|
|
952
|
+
local current: SortedNodeTostringStackEntry<T> = assert(table.remove(stack), "Must have entry") -- Pop from the stack
|
|
917
953
|
local wasSeen
|
|
918
954
|
|
|
919
955
|
if current.node then
|
|
@@ -938,11 +974,13 @@ function SortedNode:__tostring()
|
|
|
938
974
|
end
|
|
939
975
|
|
|
940
976
|
if node then
|
|
941
|
-
local text = string.format(
|
|
977
|
+
local text = string.format(
|
|
978
|
+
"SortedNode { index=%d, value=%s, descendants=%d, color=%s }",
|
|
942
979
|
node:GetIndex(),
|
|
943
980
|
tostring(node.value),
|
|
944
981
|
node.descendantCount,
|
|
945
|
-
node.color
|
|
982
|
+
node.color
|
|
983
|
+
)
|
|
946
984
|
|
|
947
985
|
if wasSeen then
|
|
948
986
|
result = result .. "<LOOPED> "
|
|
@@ -964,7 +1002,7 @@ function SortedNode:__tostring()
|
|
|
964
1002
|
return result
|
|
965
1003
|
end
|
|
966
1004
|
|
|
967
|
-
function SortedNode
|
|
1005
|
+
function SortedNode._childCount<T>(self: SortedNode<T>): number
|
|
968
1006
|
if self.left == nil and self.right == nil then
|
|
969
1007
|
return 0
|
|
970
1008
|
elseif self.left and self.right then
|
|
@@ -974,7 +1012,7 @@ function SortedNode:_childCount()
|
|
|
974
1012
|
end
|
|
975
1013
|
end
|
|
976
1014
|
|
|
977
|
-
function SortedNode
|
|
1015
|
+
function SortedNode._debugGetRoot<T>(self: SortedNode<T>): SortedNode<T>
|
|
978
1016
|
assert(DEBUG_ASSERTION_SLOW, "Must have debug enabled")
|
|
979
1017
|
|
|
980
1018
|
local seen = {}
|
|
@@ -992,7 +1030,7 @@ function SortedNode:_debugGetRoot()
|
|
|
992
1030
|
return root
|
|
993
1031
|
end
|
|
994
1032
|
|
|
995
|
-
function SortedNode
|
|
1033
|
+
function SortedNode._assertRedBlackIntegrity<T>(self: SortedNode<T>)
|
|
996
1034
|
assert(DEBUG_ASSERTION_SLOW, "Must have debug enabled")
|
|
997
1035
|
|
|
998
1036
|
-- https://en.wikipedia.org/wiki/Red%E2%80%93black_tree
|
|
@@ -1000,37 +1038,67 @@ function SortedNode:_assertRedBlackIntegrity()
|
|
|
1000
1038
|
-- Check adjacency
|
|
1001
1039
|
if self.left then
|
|
1002
1040
|
if self.left.color == Color.RED then
|
|
1003
|
-
error(
|
|
1041
|
+
error(
|
|
1042
|
+
string.format(
|
|
1043
|
+
"A red node should not have a red child %s\n%s",
|
|
1044
|
+
tostring(self:_debugGetRoot()),
|
|
1045
|
+
tostring(self)
|
|
1046
|
+
)
|
|
1047
|
+
)
|
|
1004
1048
|
end
|
|
1005
1049
|
end
|
|
1006
1050
|
|
|
1007
1051
|
if self.right then
|
|
1008
1052
|
if self.right.color == Color.RED then
|
|
1009
|
-
error(
|
|
1053
|
+
error(
|
|
1054
|
+
string.format(
|
|
1055
|
+
"A red node should not have a red child %s\n%s",
|
|
1056
|
+
tostring(self:_debugGetRoot()),
|
|
1057
|
+
tostring(self)
|
|
1058
|
+
)
|
|
1059
|
+
)
|
|
1010
1060
|
end
|
|
1011
1061
|
end
|
|
1012
1062
|
|
|
1013
1063
|
if self.parent then
|
|
1014
1064
|
if self.parent.color == Color.RED then
|
|
1015
|
-
error(
|
|
1065
|
+
error(
|
|
1066
|
+
string.format(
|
|
1067
|
+
"A red node should not be have a red parent %s\n%s",
|
|
1068
|
+
tostring(self:_debugGetRoot()),
|
|
1069
|
+
tostring(self)
|
|
1070
|
+
)
|
|
1071
|
+
)
|
|
1016
1072
|
end
|
|
1017
1073
|
end
|
|
1018
1074
|
end
|
|
1019
1075
|
|
|
1020
1076
|
if self.left ~= nil and self.right == nil then
|
|
1021
1077
|
if self.left.color ~= Color.RED then
|
|
1022
|
-
error(
|
|
1078
|
+
error(
|
|
1079
|
+
string.format(
|
|
1080
|
+
"Any node with 1 child must be red %s\n%s",
|
|
1081
|
+
tostring(self:_debugGetRoot()),
|
|
1082
|
+
tostring(self)
|
|
1083
|
+
)
|
|
1084
|
+
)
|
|
1023
1085
|
end
|
|
1024
1086
|
end
|
|
1025
1087
|
|
|
1026
1088
|
if self.left == nil and self.right ~= nil then
|
|
1027
1089
|
if self.right.color ~= Color.RED then
|
|
1028
|
-
error(
|
|
1090
|
+
error(
|
|
1091
|
+
string.format(
|
|
1092
|
+
"Any node with 1 child must be red %s\n%s",
|
|
1093
|
+
tostring(self:_debugGetRoot()),
|
|
1094
|
+
tostring(self)
|
|
1095
|
+
)
|
|
1096
|
+
)
|
|
1029
1097
|
end
|
|
1030
1098
|
end
|
|
1031
1099
|
end
|
|
1032
1100
|
|
|
1033
|
-
function SortedNode
|
|
1101
|
+
function SortedNode._assertRedBlackFullIntegritySlow<T>(self: SortedNode<T>)
|
|
1034
1102
|
assert(DEBUG_ASSERTION_SLOW, "Must have debug enabled")
|
|
1035
1103
|
|
|
1036
1104
|
local root = self:_debugGetRoot()
|
|
@@ -1042,7 +1110,7 @@ function SortedNode:_assertRedBlackFullIntegritySlow()
|
|
|
1042
1110
|
local seen = {}
|
|
1043
1111
|
|
|
1044
1112
|
local maxDepth = nil
|
|
1045
|
-
local function recurse(node
|
|
1113
|
+
local function recurse(node: SortedNode<T>, ancestorBlackCount: number)
|
|
1046
1114
|
if seen[node] then
|
|
1047
1115
|
error("Loop in nodes")
|
|
1048
1116
|
end
|
|
@@ -1059,7 +1127,13 @@ function SortedNode:_assertRedBlackFullIntegritySlow()
|
|
|
1059
1127
|
if maxDepth == nil then
|
|
1060
1128
|
maxDepth = ancestorBlackCount
|
|
1061
1129
|
elseif maxDepth ~= ancestorBlackCount then
|
|
1062
|
-
error(
|
|
1130
|
+
error(
|
|
1131
|
+
string.format(
|
|
1132
|
+
"Leaf nodes must all pass through the same amount (%d) of black nodes to root, but we are at %d",
|
|
1133
|
+
maxDepth,
|
|
1134
|
+
ancestorBlackCount
|
|
1135
|
+
)
|
|
1136
|
+
)
|
|
1063
1137
|
end
|
|
1064
1138
|
end
|
|
1065
1139
|
|
|
@@ -1069,7 +1143,13 @@ function SortedNode:_assertRedBlackFullIntegritySlow()
|
|
|
1069
1143
|
if maxDepth == nil then
|
|
1070
1144
|
maxDepth = ancestorBlackCount
|
|
1071
1145
|
elseif maxDepth ~= ancestorBlackCount then
|
|
1072
|
-
error(
|
|
1146
|
+
error(
|
|
1147
|
+
string.format(
|
|
1148
|
+
"Leaf nodes must all pass through the same amount (%d) of black nodes to root but we are at %d",
|
|
1149
|
+
maxDepth,
|
|
1150
|
+
ancestorBlackCount
|
|
1151
|
+
)
|
|
1152
|
+
)
|
|
1073
1153
|
end
|
|
1074
1154
|
end
|
|
1075
1155
|
end
|
|
@@ -1078,7 +1158,7 @@ function SortedNode:_assertRedBlackFullIntegritySlow()
|
|
|
1078
1158
|
recurse(root, 0)
|
|
1079
1159
|
end
|
|
1080
1160
|
|
|
1081
|
-
function SortedNode
|
|
1161
|
+
function SortedNode._assertIntegrity<T>(self: SortedNode<T>)
|
|
1082
1162
|
assert(DEBUG_ASSERTION_SLOW, "Must have debug enabled")
|
|
1083
1163
|
assert(self.left ~= self, "Node cannot be parented to self")
|
|
1084
1164
|
assert(self.right ~= self, "Node cannot be parented to self")
|
|
@@ -1090,13 +1170,25 @@ function SortedNode:_assertIntegrity()
|
|
|
1090
1170
|
|
|
1091
1171
|
if parent.left == self then
|
|
1092
1172
|
if self.value > parent.value then
|
|
1093
|
-
error(
|
|
1173
|
+
error(
|
|
1174
|
+
string.format(
|
|
1175
|
+
"self.parent.left.value %s >= parent.value %s",
|
|
1176
|
+
self:_valueToHumanReadable(),
|
|
1177
|
+
parent:_valueToHumanReadable()
|
|
1178
|
+
)
|
|
1179
|
+
)
|
|
1094
1180
|
end
|
|
1095
1181
|
end
|
|
1096
1182
|
|
|
1097
1183
|
if parent.right == self then
|
|
1098
1184
|
if self.value < parent.value then
|
|
1099
|
-
error(
|
|
1185
|
+
error(
|
|
1186
|
+
string.format(
|
|
1187
|
+
"self.parent.right.value %s <= parent.value %s",
|
|
1188
|
+
self:_valueToHumanReadable(),
|
|
1189
|
+
parent:_valueToHumanReadable()
|
|
1190
|
+
)
|
|
1191
|
+
)
|
|
1100
1192
|
end
|
|
1101
1193
|
end
|
|
1102
1194
|
end
|
|
@@ -1107,7 +1199,13 @@ function SortedNode:_assertIntegrity()
|
|
|
1107
1199
|
assert(left.parent == self, "Left parent is not set to us")
|
|
1108
1200
|
|
|
1109
1201
|
if left.value > self.value then
|
|
1110
|
-
error(
|
|
1202
|
+
error(
|
|
1203
|
+
string.format(
|
|
1204
|
+
"left.value %s > self.value %s",
|
|
1205
|
+
left:_valueToHumanReadable(),
|
|
1206
|
+
self:_valueToHumanReadable()
|
|
1207
|
+
)
|
|
1208
|
+
)
|
|
1111
1209
|
end
|
|
1112
1210
|
|
|
1113
1211
|
descendantCount += left.descendantCount
|
|
@@ -1118,7 +1216,13 @@ function SortedNode:_assertIntegrity()
|
|
|
1118
1216
|
assert(right.parent == self, "Right parent is not set to us")
|
|
1119
1217
|
|
|
1120
1218
|
if right.value < self.value then
|
|
1121
|
-
error(
|
|
1219
|
+
error(
|
|
1220
|
+
string.format(
|
|
1221
|
+
"right.value %s <= self.value %s",
|
|
1222
|
+
right:_valueToHumanReadable(),
|
|
1223
|
+
self:_valueToHumanReadable()
|
|
1224
|
+
)
|
|
1225
|
+
)
|
|
1122
1226
|
end
|
|
1123
1227
|
|
|
1124
1228
|
descendantCount += right.descendantCount
|
|
@@ -1129,7 +1233,18 @@ function SortedNode:_assertIntegrity()
|
|
|
1129
1233
|
end
|
|
1130
1234
|
end
|
|
1131
1235
|
|
|
1132
|
-
function SortedNode:
|
|
1236
|
+
function SortedNode._valueToHumanReadable<T>(self: SortedNode<T>): string
|
|
1237
|
+
local value: any = self.value
|
|
1238
|
+
if type(value) == "number" then
|
|
1239
|
+
return string.format("%0.2f", value)
|
|
1240
|
+
elseif SortedNodeValue.isSortedNodeValue(value) then
|
|
1241
|
+
return tostring(value)
|
|
1242
|
+
else
|
|
1243
|
+
error(string.format("Bad value %s", tostring(value)))
|
|
1244
|
+
end
|
|
1245
|
+
end
|
|
1246
|
+
|
|
1247
|
+
function SortedNode._assertFullIntegritySlow<T>(self: SortedNode<T>)
|
|
1133
1248
|
assert(DEBUG_ASSERTION_SLOW, "Must have debug enabled")
|
|
1134
1249
|
|
|
1135
1250
|
local root = self:_debugGetRoot()
|
|
@@ -1154,13 +1269,13 @@ function SortedNode:_assertFullIntegritySlow()
|
|
|
1154
1269
|
end
|
|
1155
1270
|
end
|
|
1156
1271
|
|
|
1157
|
-
function SortedNode
|
|
1272
|
+
function SortedNode._assertRootIntegrity<T>(self: SortedNode<T>)
|
|
1158
1273
|
assert(DEBUG_ASSERTION_SLOW, "Must have debug enabled")
|
|
1159
1274
|
assert(self.parent == nil, "Root should not have a parent")
|
|
1160
1275
|
assert(self.color == Color.BLACK, "Root should be black")
|
|
1161
1276
|
end
|
|
1162
1277
|
|
|
1163
|
-
function SortedNode
|
|
1278
|
+
function SortedNode._assertDescendantCount<T>(self: SortedNode<T>, expected: number)
|
|
1164
1279
|
assert(DEBUG_ASSERTION_SLOW, "Must have debug enabled")
|
|
1165
1280
|
|
|
1166
1281
|
if self.descendantCount ~= expected then
|