articulated 1.3.1 → 1.3.2
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 +1 -1
- package/build/commonjs/id_list.d.ts +12 -0
- package/build/commonjs/id_list.js +6 -0
- package/build/commonjs/id_list.js.map +1 -1
- package/build/commonjs/internal/leaf_map.js +2 -5
- package/build/commonjs/internal/leaf_map.js.map +1 -1
- package/build/commonjs/internal/seq_map.d.ts +2 -2
- package/build/commonjs/internal/seq_map.js +2 -5
- package/build/commonjs/internal/seq_map.js.map +1 -1
- package/build/commonjs/vendor/functional-red-black-tree.d.ts +92 -7
- package/build/commonjs/vendor/functional-red-black-tree.js +439 -694
- package/build/commonjs/vendor/functional-red-black-tree.js.map +1 -1
- package/build/esm/id_list.d.ts +12 -0
- package/build/esm/id_list.js +7 -1
- package/build/esm/id_list.js.map +1 -1
- package/build/esm/internal/leaf_map.js +2 -2
- package/build/esm/internal/leaf_map.js.map +1 -1
- package/build/esm/internal/seq_map.d.ts +2 -2
- package/build/esm/internal/seq_map.js +2 -2
- package/build/esm/internal/seq_map.js.map +1 -1
- package/build/esm/vendor/functional-red-black-tree.d.ts +92 -7
- package/build/esm/vendor/functional-red-black-tree.js +434 -695
- package/build/esm/vendor/functional-red-black-tree.js.map +1 -1
- package/package.json +1 -1
- package/src/id_list.ts +13 -1
- package/src/internal/leaf_map.ts +3 -3
- package/src/internal/seq_map.ts +3 -3
- package/src/vendor/functional-red-black-tree.ts +653 -0
- package/src/vendor/functional-red-black-tree.d.ts +0 -177
- package/src/vendor/functional-red-black-tree.js +0 -938
|
@@ -1,495 +1,343 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
module.exports = createRBTree;
|
|
3
1
|
// Modified from https://github.com/mikolalysenko/functional-red-black-tree/blob/master/rbtree.js
|
|
4
2
|
// which is MIT Licensed, Copyright (c) 2013 Mikola Lysenko.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
//
|
|
4
|
+
// External types modified from
|
|
5
|
+
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/functional-red-black-tree/functional-red-black-tree-tests.ts
|
|
6
|
+
// which is MIT Licensed.
|
|
7
|
+
const RED = 0;
|
|
8
|
+
const BLACK = 1;
|
|
9
|
+
/**
|
|
10
|
+
* @private Only exported for tests.
|
|
11
|
+
*/
|
|
12
|
+
export class RBNode {
|
|
13
|
+
constructor(color,
|
|
14
|
+
/** The key associated with the node. */
|
|
15
|
+
key,
|
|
16
|
+
/** The value associated with the node. */
|
|
17
|
+
value,
|
|
18
|
+
/** The left subtree of the node. */
|
|
19
|
+
left,
|
|
20
|
+
/** The right subtree of the node. */
|
|
21
|
+
right) {
|
|
22
|
+
this.color = color;
|
|
23
|
+
this.key = key;
|
|
24
|
+
this.value = value;
|
|
25
|
+
this.left = left;
|
|
26
|
+
this.right = right;
|
|
27
|
+
}
|
|
13
28
|
}
|
|
14
29
|
function cloneNode(node) {
|
|
15
|
-
return new RBNode(node.
|
|
30
|
+
return new RBNode(node.color, node.key, node.value, node.left, node.right);
|
|
16
31
|
}
|
|
17
32
|
function repaint(color, node) {
|
|
18
33
|
return new RBNode(color, node.key, node.value, node.left, node.right);
|
|
19
34
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// Object.defineProperty(proto, "keys", {
|
|
26
|
-
// get: function () {
|
|
27
|
-
// var result = [];
|
|
28
|
-
// this.forEach(function (k, v) {
|
|
29
|
-
// result.push(k);
|
|
30
|
-
// });
|
|
31
|
-
// return result;
|
|
32
|
-
// },
|
|
33
|
-
// });
|
|
34
|
-
// Object.defineProperty(proto, "values", {
|
|
35
|
-
// get: function () {
|
|
36
|
-
// var result = [];
|
|
37
|
-
// this.forEach(function (k, v) {
|
|
38
|
-
// result.push(v);
|
|
39
|
-
// });
|
|
40
|
-
// return result;
|
|
41
|
-
// },
|
|
42
|
-
// });
|
|
43
|
-
//Set a key-value pair
|
|
44
|
-
proto.set = function (key, value) {
|
|
45
|
-
var cmp = this._compare;
|
|
46
|
-
//Find point to insert/replace node
|
|
47
|
-
var n = this.root;
|
|
48
|
-
var n_stack = [];
|
|
49
|
-
var d_stack = [];
|
|
50
|
-
let d = 0;
|
|
51
|
-
while (n) {
|
|
52
|
-
d = cmp(key, n.key);
|
|
53
|
-
n_stack.push(n);
|
|
54
|
-
d_stack.push(d);
|
|
55
|
-
// If the keys are equivalent, skip straight to the replace = true case.
|
|
56
|
-
if (d === 0)
|
|
57
|
-
break;
|
|
58
|
-
else if (d < 0) {
|
|
59
|
-
n = n.left;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
n = n.right;
|
|
63
|
-
}
|
|
35
|
+
/** Represents a functional red-black tree. */
|
|
36
|
+
export class RedBlackTree {
|
|
37
|
+
constructor(compare, root) {
|
|
38
|
+
this.compare = compare;
|
|
39
|
+
this.root = root;
|
|
64
40
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Creates an empty red-black tree.
|
|
43
|
+
*
|
|
44
|
+
* @param compare Comparison function, same semantics as array.sort().
|
|
45
|
+
* @returns An empty tree ordered by `compare`.
|
|
46
|
+
*/
|
|
47
|
+
static new(compare) {
|
|
48
|
+
return new RedBlackTree(compare, null);
|
|
73
49
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Creates a new tree with `key` set to `value`, overwriting any
|
|
52
|
+
* existing value.
|
|
53
|
+
*
|
|
54
|
+
* @param key The key of the item to insert.
|
|
55
|
+
* @param value The value of the item to insert.
|
|
56
|
+
* @returns A new tree with `key` set to `value`.
|
|
57
|
+
*/
|
|
58
|
+
set(key, value) {
|
|
59
|
+
const cmp = this.compare;
|
|
60
|
+
//Find point to insert/replace node
|
|
61
|
+
let n = this.root;
|
|
62
|
+
const n_stack = [];
|
|
63
|
+
const d_stack = [];
|
|
64
|
+
let d = 0;
|
|
65
|
+
while (n) {
|
|
66
|
+
d = cmp(key, n.key);
|
|
67
|
+
n_stack.push(n);
|
|
68
|
+
d_stack.push(d);
|
|
69
|
+
// If the keys are equivalent, skip straight to the replace = true case.
|
|
70
|
+
if (d === 0)
|
|
71
|
+
break;
|
|
72
|
+
else if (d < 0) {
|
|
73
|
+
n = n.left;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
n = n.right;
|
|
77
|
+
}
|
|
82
78
|
}
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
const replace = d === 0 && n_stack.length > 0;
|
|
80
|
+
if (replace) {
|
|
81
|
+
// The last node in the n_stack has key equivalent to `key`.
|
|
82
|
+
// Replace its entry without changing the tree structure.
|
|
83
|
+
const lastN = n_stack[n_stack.length - 1];
|
|
84
|
+
if (lastN.key === key && lastN.value === value)
|
|
85
|
+
return this;
|
|
86
|
+
n_stack[n_stack.length - 1] = new RBNode(lastN.color, key, value, lastN.left, lastN.right);
|
|
85
87
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return new RedBlackTree(cmp, n_stack[0]);
|
|
89
|
-
//Rebalance tree using rotations
|
|
90
|
-
//console.log("start insert", key, d_stack)
|
|
91
|
-
for (var s = n_stack.length - 1; s > 1; --s) {
|
|
92
|
-
var p = n_stack[s - 1];
|
|
93
|
-
var n = n_stack[s];
|
|
94
|
-
if (p._color === BLACK || n._color === BLACK) {
|
|
95
|
-
break;
|
|
88
|
+
else {
|
|
89
|
+
n_stack.push(new RBNode(RED, key, value, null, null));
|
|
96
90
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
p._color = BLACK;
|
|
104
|
-
pp.right = repaint(BLACK, y);
|
|
105
|
-
pp._color = RED;
|
|
106
|
-
s -= 1;
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
//console.log("LLb")
|
|
110
|
-
pp._color = RED;
|
|
111
|
-
pp.left = p.right;
|
|
112
|
-
p._color = BLACK;
|
|
113
|
-
p.right = pp;
|
|
114
|
-
n_stack[s - 2] = p;
|
|
115
|
-
n_stack[s - 1] = n;
|
|
116
|
-
if (s >= 3) {
|
|
117
|
-
var ppp = n_stack[s - 3];
|
|
118
|
-
if (ppp.left === pp) {
|
|
119
|
-
ppp.left = p;
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
ppp.right = p;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
91
|
+
//Rebuild path to leaf node
|
|
92
|
+
let s;
|
|
93
|
+
for (s = n_stack.length - 2; s >= 0; --s) {
|
|
94
|
+
n = n_stack[s];
|
|
95
|
+
if (d_stack[s] <= 0) {
|
|
96
|
+
n_stack[s] = new RBNode(n.color, n.key, n.value, n_stack[s + 1], n.right);
|
|
127
97
|
}
|
|
128
98
|
else {
|
|
129
|
-
|
|
130
|
-
if (y && y._color === RED) {
|
|
131
|
-
//console.log("LRr")
|
|
132
|
-
p._color = BLACK;
|
|
133
|
-
pp.right = repaint(BLACK, y);
|
|
134
|
-
pp._color = RED;
|
|
135
|
-
s -= 1;
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
//console.log("LRb")
|
|
139
|
-
p.right = n.left;
|
|
140
|
-
pp._color = RED;
|
|
141
|
-
pp.left = n.right;
|
|
142
|
-
n._color = BLACK;
|
|
143
|
-
n.left = p;
|
|
144
|
-
n.right = pp;
|
|
145
|
-
n_stack[s - 2] = n;
|
|
146
|
-
n_stack[s - 1] = p;
|
|
147
|
-
if (s >= 3) {
|
|
148
|
-
var ppp = n_stack[s - 3];
|
|
149
|
-
if (ppp.left === pp) {
|
|
150
|
-
ppp.left = n;
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
ppp.right = n;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
99
|
+
n_stack[s] = new RBNode(n.color, n.key, n.value, n.left, n_stack[s + 1]);
|
|
158
100
|
}
|
|
159
101
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
102
|
+
if (replace)
|
|
103
|
+
return new RedBlackTree(cmp, n_stack[0]);
|
|
104
|
+
//Rebalance tree using rotations
|
|
105
|
+
//console.log("start insert", key, d_stack)
|
|
106
|
+
for (s = n_stack.length - 1; s > 1; --s) {
|
|
107
|
+
const p = n_stack[s - 1];
|
|
108
|
+
n = n_stack[s];
|
|
109
|
+
if (p.color === BLACK || n.color === BLACK) {
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
const pp = n_stack[s - 2];
|
|
113
|
+
if (pp.left === p) {
|
|
114
|
+
if (p.left === n) {
|
|
115
|
+
const y = pp.right;
|
|
116
|
+
if (y && y.color === RED) {
|
|
117
|
+
//console.log("LLr")
|
|
118
|
+
p.color = BLACK;
|
|
119
|
+
pp.right = repaint(BLACK, y);
|
|
120
|
+
pp.color = RED;
|
|
121
|
+
s -= 1;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
//console.log("LLb")
|
|
125
|
+
pp.color = RED;
|
|
126
|
+
pp.left = p.right;
|
|
127
|
+
p.color = BLACK;
|
|
128
|
+
p.right = pp;
|
|
129
|
+
n_stack[s - 2] = p;
|
|
130
|
+
n_stack[s - 1] = n;
|
|
131
|
+
if (s >= 3) {
|
|
132
|
+
const ppp = n_stack[s - 3];
|
|
133
|
+
if (ppp.left === pp) {
|
|
134
|
+
ppp.left = p;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
ppp.right = p;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
169
142
|
}
|
|
170
143
|
else {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
144
|
+
const y = pp.right;
|
|
145
|
+
if (y && y.color === RED) {
|
|
146
|
+
//console.log("LRr")
|
|
147
|
+
p.color = BLACK;
|
|
148
|
+
pp.right = repaint(BLACK, y);
|
|
149
|
+
pp.color = RED;
|
|
150
|
+
s -= 1;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
//console.log("LRb")
|
|
154
|
+
p.right = n.left;
|
|
155
|
+
pp.color = RED;
|
|
156
|
+
pp.left = n.right;
|
|
157
|
+
n.color = BLACK;
|
|
158
|
+
n.left = p;
|
|
159
|
+
n.right = pp;
|
|
160
|
+
n_stack[s - 2] = n;
|
|
161
|
+
n_stack[s - 1] = p;
|
|
162
|
+
if (s >= 3) {
|
|
163
|
+
const ppp = n_stack[s - 3];
|
|
164
|
+
if (ppp.left === pp) {
|
|
165
|
+
ppp.left = n;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
ppp.right = n;
|
|
169
|
+
}
|
|
185
170
|
}
|
|
171
|
+
break;
|
|
186
172
|
}
|
|
187
|
-
break;
|
|
188
173
|
}
|
|
189
174
|
}
|
|
190
175
|
else {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
176
|
+
if (p.right === n) {
|
|
177
|
+
const y = pp.left;
|
|
178
|
+
if (y && y.color === RED) {
|
|
179
|
+
//console.log("RRr", y.key)
|
|
180
|
+
p.color = BLACK;
|
|
181
|
+
pp.left = repaint(BLACK, y);
|
|
182
|
+
pp.color = RED;
|
|
183
|
+
s -= 1;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
//console.log("RRb")
|
|
187
|
+
pp.color = RED;
|
|
188
|
+
pp.right = p.left;
|
|
189
|
+
p.color = BLACK;
|
|
190
|
+
p.left = pp;
|
|
191
|
+
n_stack[s - 2] = p;
|
|
192
|
+
n_stack[s - 1] = n;
|
|
193
|
+
if (s >= 3) {
|
|
194
|
+
const ppp = n_stack[s - 3];
|
|
195
|
+
if (ppp.right === pp) {
|
|
196
|
+
ppp.right = p;
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
ppp.left = p;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
198
204
|
}
|
|
199
205
|
else {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
206
|
+
const y = pp.left;
|
|
207
|
+
if (y && y.color === RED) {
|
|
208
|
+
//console.log("RLr")
|
|
209
|
+
p.color = BLACK;
|
|
210
|
+
pp.left = repaint(BLACK, y);
|
|
211
|
+
pp.color = RED;
|
|
212
|
+
s -= 1;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
//console.log("RLb")
|
|
216
|
+
p.left = n.right;
|
|
217
|
+
pp.color = RED;
|
|
218
|
+
pp.right = n.left;
|
|
219
|
+
n.color = BLACK;
|
|
220
|
+
n.right = p;
|
|
221
|
+
n.left = pp;
|
|
222
|
+
n_stack[s - 2] = n;
|
|
223
|
+
n_stack[s - 1] = p;
|
|
224
|
+
if (s >= 3) {
|
|
225
|
+
const ppp = n_stack[s - 3];
|
|
226
|
+
if (ppp.right === pp) {
|
|
227
|
+
ppp.right = n;
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
ppp.left = n;
|
|
231
|
+
}
|
|
216
232
|
}
|
|
233
|
+
break;
|
|
217
234
|
}
|
|
218
|
-
break;
|
|
219
235
|
}
|
|
220
236
|
}
|
|
221
237
|
}
|
|
238
|
+
//Return new tree
|
|
239
|
+
n_stack[0].color = BLACK;
|
|
240
|
+
return new RedBlackTree(cmp, n_stack[0]);
|
|
222
241
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
// if (l <= 0) {
|
|
247
|
-
// if (node.left) {
|
|
248
|
-
// var v = doVisitHalf(lo, compare, visit, node.left);
|
|
249
|
-
// if (v) {
|
|
250
|
-
// return v;
|
|
251
|
-
// }
|
|
252
|
-
// }
|
|
253
|
-
// var v = visit(node.key, node.value);
|
|
254
|
-
// if (v) {
|
|
255
|
-
// return v;
|
|
256
|
-
// }
|
|
257
|
-
// }
|
|
258
|
-
// if (node.right) {
|
|
259
|
-
// return doVisitHalf(lo, compare, visit, node.right);
|
|
260
|
-
// }
|
|
261
|
-
// }
|
|
262
|
-
// //Visit all nodes within a range
|
|
263
|
-
// function doVisit(lo, hi, compare, visit, node) {
|
|
264
|
-
// var l = compare(lo, node.key);
|
|
265
|
-
// var h = compare(hi, node.key);
|
|
266
|
-
// var v;
|
|
267
|
-
// if (l <= 0) {
|
|
268
|
-
// if (node.left) {
|
|
269
|
-
// v = doVisit(lo, hi, compare, visit, node.left);
|
|
270
|
-
// if (v) {
|
|
271
|
-
// return v;
|
|
272
|
-
// }
|
|
273
|
-
// }
|
|
274
|
-
// if (h > 0) {
|
|
275
|
-
// v = visit(node.key, node.value);
|
|
276
|
-
// if (v) {
|
|
277
|
-
// return v;
|
|
278
|
-
// }
|
|
279
|
-
// }
|
|
280
|
-
// }
|
|
281
|
-
// if (h > 0 && node.right) {
|
|
282
|
-
// return doVisit(lo, hi, compare, visit, node.right);
|
|
283
|
-
// }
|
|
284
|
-
// }
|
|
285
|
-
// proto.forEach = function rbTreeForEach(visit, lo, hi) {
|
|
286
|
-
// if (!this.root) {
|
|
287
|
-
// return;
|
|
288
|
-
// }
|
|
289
|
-
// switch (arguments.length) {
|
|
290
|
-
// case 1:
|
|
291
|
-
// return doVisitFull(visit, this.root);
|
|
292
|
-
// break;
|
|
293
|
-
// case 2:
|
|
294
|
-
// return doVisitHalf(lo, this._compare, visit, this.root);
|
|
295
|
-
// break;
|
|
296
|
-
// case 3:
|
|
297
|
-
// if (this._compare(lo, hi) >= 0) {
|
|
298
|
-
// return;
|
|
299
|
-
// }
|
|
300
|
-
// return doVisit(lo, hi, this._compare, visit, this.root);
|
|
301
|
-
// break;
|
|
302
|
-
// }
|
|
303
|
-
// };
|
|
304
|
-
// //First item in list
|
|
305
|
-
// Object.defineProperty(proto, "begin", {
|
|
306
|
-
// get: function () {
|
|
307
|
-
// var stack = [];
|
|
308
|
-
// var n = this.root;
|
|
309
|
-
// while (n) {
|
|
310
|
-
// stack.push(n);
|
|
311
|
-
// n = n.left;
|
|
312
|
-
// }
|
|
313
|
-
// return new RedBlackTreeIterator(this, stack);
|
|
314
|
-
// },
|
|
315
|
-
// });
|
|
316
|
-
// //Last item in list
|
|
317
|
-
// Object.defineProperty(proto, "end", {
|
|
318
|
-
// get: function () {
|
|
319
|
-
// var stack = [];
|
|
320
|
-
// var n = this.root;
|
|
321
|
-
// while (n) {
|
|
322
|
-
// stack.push(n);
|
|
323
|
-
// n = n.right;
|
|
324
|
-
// }
|
|
325
|
-
// return new RedBlackTreeIterator(this, stack);
|
|
326
|
-
// },
|
|
327
|
-
// });
|
|
328
|
-
// proto.ge = function (key) {
|
|
329
|
-
// var cmp = this._compare;
|
|
330
|
-
// var n = this.root;
|
|
331
|
-
// var stack = [];
|
|
332
|
-
// var last_ptr = 0;
|
|
333
|
-
// while (n) {
|
|
334
|
-
// var d = cmp(key, n.key);
|
|
335
|
-
// stack.push(n);
|
|
336
|
-
// if (d <= 0) {
|
|
337
|
-
// last_ptr = stack.length;
|
|
338
|
-
// }
|
|
339
|
-
// if (d <= 0) {
|
|
340
|
-
// n = n.left;
|
|
341
|
-
// } else {
|
|
342
|
-
// n = n.right;
|
|
343
|
-
// }
|
|
344
|
-
// }
|
|
345
|
-
// stack.length = last_ptr;
|
|
346
|
-
// return new RedBlackTreeIterator(this, stack);
|
|
347
|
-
// };
|
|
348
|
-
// proto.gt = function (key) {
|
|
349
|
-
// var cmp = this._compare;
|
|
350
|
-
// var n = this.root;
|
|
351
|
-
// var stack = [];
|
|
352
|
-
// var last_ptr = 0;
|
|
353
|
-
// while (n) {
|
|
354
|
-
// var d = cmp(key, n.key);
|
|
355
|
-
// stack.push(n);
|
|
356
|
-
// if (d < 0) {
|
|
357
|
-
// last_ptr = stack.length;
|
|
358
|
-
// }
|
|
359
|
-
// if (d < 0) {
|
|
360
|
-
// n = n.left;
|
|
361
|
-
// } else {
|
|
362
|
-
// n = n.right;
|
|
363
|
-
// }
|
|
364
|
-
// }
|
|
365
|
-
// stack.length = last_ptr;
|
|
366
|
-
// return new RedBlackTreeIterator(this, stack);
|
|
367
|
-
// };
|
|
368
|
-
// proto.lt = function (key) {
|
|
369
|
-
// var cmp = this._compare;
|
|
370
|
-
// var n = this.root;
|
|
371
|
-
// var stack = [];
|
|
372
|
-
// var last_ptr = 0;
|
|
373
|
-
// while (n) {
|
|
374
|
-
// var d = cmp(key, n.key);
|
|
375
|
-
// stack.push(n);
|
|
376
|
-
// if (d > 0) {
|
|
377
|
-
// last_ptr = stack.length;
|
|
378
|
-
// }
|
|
379
|
-
// if (d <= 0) {
|
|
380
|
-
// n = n.left;
|
|
381
|
-
// } else {
|
|
382
|
-
// n = n.right;
|
|
383
|
-
// }
|
|
384
|
-
// }
|
|
385
|
-
// stack.length = last_ptr;
|
|
386
|
-
// return new RedBlackTreeIterator(this, stack);
|
|
387
|
-
// };
|
|
388
|
-
proto.le = function (key) {
|
|
389
|
-
var cmp = this._compare;
|
|
390
|
-
var n = this.root;
|
|
391
|
-
var stack = [];
|
|
392
|
-
var last_ptr = 0;
|
|
393
|
-
while (n) {
|
|
394
|
-
var d = cmp(key, n.key);
|
|
395
|
-
stack.push(n);
|
|
396
|
-
if (d >= 0) {
|
|
397
|
-
last_ptr = stack.length;
|
|
398
|
-
}
|
|
399
|
-
if (d < 0) {
|
|
400
|
-
n = n.left;
|
|
401
|
-
}
|
|
402
|
-
else {
|
|
403
|
-
n = n.right;
|
|
242
|
+
/**
|
|
243
|
+
* Finds the last item in the tree whose key is <= `key`.
|
|
244
|
+
*
|
|
245
|
+
* @param key The key to search for.
|
|
246
|
+
* @returns An iterator at the given element.
|
|
247
|
+
*/
|
|
248
|
+
le(key) {
|
|
249
|
+
const cmp = this.compare;
|
|
250
|
+
let n = this.root;
|
|
251
|
+
const stack = [];
|
|
252
|
+
let last_ptr = 0;
|
|
253
|
+
while (n) {
|
|
254
|
+
const d = cmp(key, n.key);
|
|
255
|
+
stack.push(n);
|
|
256
|
+
if (d >= 0) {
|
|
257
|
+
last_ptr = stack.length;
|
|
258
|
+
}
|
|
259
|
+
if (d < 0) {
|
|
260
|
+
n = n.left;
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
n = n.right;
|
|
264
|
+
}
|
|
404
265
|
}
|
|
266
|
+
stack.length = last_ptr;
|
|
267
|
+
return new RedBlackTreeIterator(this, stack);
|
|
405
268
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
269
|
+
/**
|
|
270
|
+
* @returns An iterator pointing to the first item in the tree with `key`, otherwise null.
|
|
271
|
+
*/
|
|
272
|
+
find(key) {
|
|
273
|
+
const cmp = this.compare;
|
|
274
|
+
let n = this.root;
|
|
275
|
+
const stack = [];
|
|
276
|
+
while (n) {
|
|
277
|
+
const d = cmp(key, n.key);
|
|
278
|
+
stack.push(n);
|
|
279
|
+
if (d === 0) {
|
|
280
|
+
return new RedBlackTreeIterator(this, stack);
|
|
281
|
+
}
|
|
282
|
+
if (d <= 0) {
|
|
283
|
+
n = n.left;
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
n = n.right;
|
|
287
|
+
}
|
|
425
288
|
}
|
|
289
|
+
return new RedBlackTreeIterator(this, []);
|
|
426
290
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
291
|
+
/**
|
|
292
|
+
* Removes the first item with `key` in the tree.
|
|
293
|
+
*
|
|
294
|
+
* @param key The key of the item to remove.
|
|
295
|
+
* @returns A new tree with the given item removed, if it exists.
|
|
296
|
+
*/
|
|
297
|
+
remove(key) {
|
|
298
|
+
const iter = this.find(key);
|
|
299
|
+
return iter.remove();
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Retrieves the value associated with `key`.
|
|
303
|
+
*
|
|
304
|
+
* @param key The key of the item to look up.
|
|
305
|
+
* @returns The value of the first node associated with `key`.
|
|
306
|
+
*/
|
|
307
|
+
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
308
|
+
get(key) {
|
|
309
|
+
const cmp = this.compare;
|
|
310
|
+
let n = this.root;
|
|
311
|
+
while (n) {
|
|
312
|
+
const d = cmp(key, n.key);
|
|
313
|
+
if (d === 0) {
|
|
314
|
+
return n.value;
|
|
315
|
+
}
|
|
316
|
+
if (d <= 0) {
|
|
317
|
+
n = n.left;
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
n = n.right;
|
|
321
|
+
}
|
|
448
322
|
}
|
|
323
|
+
return;
|
|
449
324
|
}
|
|
450
|
-
return;
|
|
451
|
-
};
|
|
452
|
-
//Iterator for red black tree
|
|
453
|
-
function RedBlackTreeIterator(tree, stack) {
|
|
454
|
-
this.tree = tree;
|
|
455
|
-
this._stack = stack;
|
|
456
325
|
}
|
|
457
|
-
var iproto = RedBlackTreeIterator.prototype;
|
|
458
|
-
// //Test if iterator is valid
|
|
459
|
-
// Object.defineProperty(iproto, "valid", {
|
|
460
|
-
// get: function () {
|
|
461
|
-
// return this._stack.length > 0;
|
|
462
|
-
// },
|
|
463
|
-
// });
|
|
464
|
-
// //Node of the iterator
|
|
465
|
-
// Object.defineProperty(iproto, "node", {
|
|
466
|
-
// get: function () {
|
|
467
|
-
// if (this._stack.length > 0) {
|
|
468
|
-
// return this._stack[this._stack.length - 1];
|
|
469
|
-
// }
|
|
470
|
-
// return null;
|
|
471
|
-
// },
|
|
472
|
-
// enumerable: true,
|
|
473
|
-
// });
|
|
474
|
-
// //Makes a copy of an iterator
|
|
475
|
-
// iproto.clone = function () {
|
|
476
|
-
// return new RedBlackTreeIterator(this.tree, this._stack.slice());
|
|
477
|
-
// };
|
|
478
326
|
//Swaps two nodes
|
|
479
327
|
function swapNode(n, v) {
|
|
480
328
|
n.key = v.key;
|
|
481
329
|
n.value = v.value;
|
|
482
330
|
n.left = v.left;
|
|
483
331
|
n.right = v.right;
|
|
484
|
-
n.
|
|
332
|
+
n.color = v.color;
|
|
485
333
|
}
|
|
486
334
|
//Fix up a double black node in a tree
|
|
487
335
|
function fixDoubleBlack(stack) {
|
|
488
|
-
|
|
489
|
-
for (
|
|
336
|
+
let n, p, s, z;
|
|
337
|
+
for (let i = stack.length - 1; i >= 0; --i) {
|
|
490
338
|
n = stack[i];
|
|
491
339
|
if (i === 0) {
|
|
492
|
-
n.
|
|
340
|
+
n.color = BLACK;
|
|
493
341
|
return;
|
|
494
342
|
}
|
|
495
343
|
//console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key)
|
|
@@ -497,19 +345,19 @@ function fixDoubleBlack(stack) {
|
|
|
497
345
|
if (p.left === n) {
|
|
498
346
|
//console.log("left child")
|
|
499
347
|
s = p.right;
|
|
500
|
-
if (s.right && s.right.
|
|
348
|
+
if (s.right && s.right.color === RED) {
|
|
501
349
|
//console.log("case 1: right sibling child red")
|
|
502
350
|
s = p.right = cloneNode(s);
|
|
503
351
|
z = s.right = cloneNode(s.right);
|
|
504
352
|
p.right = s.left;
|
|
505
353
|
s.left = p;
|
|
506
354
|
s.right = z;
|
|
507
|
-
s.
|
|
508
|
-
n.
|
|
509
|
-
p.
|
|
510
|
-
z.
|
|
355
|
+
s.color = p.color;
|
|
356
|
+
n.color = BLACK;
|
|
357
|
+
p.color = BLACK;
|
|
358
|
+
z.color = BLACK;
|
|
511
359
|
if (i > 1) {
|
|
512
|
-
|
|
360
|
+
const pp = stack[i - 2];
|
|
513
361
|
if (pp.left === p) {
|
|
514
362
|
pp.left = s;
|
|
515
363
|
}
|
|
@@ -520,7 +368,7 @@ function fixDoubleBlack(stack) {
|
|
|
520
368
|
stack[i - 1] = s;
|
|
521
369
|
return;
|
|
522
370
|
}
|
|
523
|
-
else if (s.left && s.left.
|
|
371
|
+
else if (s.left && s.left.color === RED) {
|
|
524
372
|
//console.log("case 1: left sibling child red")
|
|
525
373
|
s = p.right = cloneNode(s);
|
|
526
374
|
z = s.left = cloneNode(s.left);
|
|
@@ -528,12 +376,12 @@ function fixDoubleBlack(stack) {
|
|
|
528
376
|
s.left = z.right;
|
|
529
377
|
z.left = p;
|
|
530
378
|
z.right = s;
|
|
531
|
-
z.
|
|
532
|
-
p.
|
|
533
|
-
s.
|
|
534
|
-
n.
|
|
379
|
+
z.color = p.color;
|
|
380
|
+
p.color = BLACK;
|
|
381
|
+
s.color = BLACK;
|
|
382
|
+
n.color = BLACK;
|
|
535
383
|
if (i > 1) {
|
|
536
|
-
|
|
384
|
+
const pp = stack[i - 2];
|
|
537
385
|
if (pp.left === p) {
|
|
538
386
|
pp.left = z;
|
|
539
387
|
}
|
|
@@ -544,10 +392,10 @@ function fixDoubleBlack(stack) {
|
|
|
544
392
|
stack[i - 1] = z;
|
|
545
393
|
return;
|
|
546
394
|
}
|
|
547
|
-
if (s.
|
|
548
|
-
if (p.
|
|
395
|
+
if (s.color === BLACK) {
|
|
396
|
+
if (p.color === RED) {
|
|
549
397
|
//console.log("case 2: black sibling, red parent", p.right.value)
|
|
550
|
-
p.
|
|
398
|
+
p.color = BLACK;
|
|
551
399
|
p.right = repaint(RED, s);
|
|
552
400
|
return;
|
|
553
401
|
}
|
|
@@ -562,10 +410,10 @@ function fixDoubleBlack(stack) {
|
|
|
562
410
|
s = cloneNode(s);
|
|
563
411
|
p.right = s.left;
|
|
564
412
|
s.left = p;
|
|
565
|
-
s.
|
|
566
|
-
p.
|
|
413
|
+
s.color = p.color;
|
|
414
|
+
p.color = RED;
|
|
567
415
|
if (i > 1) {
|
|
568
|
-
|
|
416
|
+
const pp = stack[i - 2];
|
|
569
417
|
if (pp.left === p) {
|
|
570
418
|
pp.left = s;
|
|
571
419
|
}
|
|
@@ -587,19 +435,19 @@ function fixDoubleBlack(stack) {
|
|
|
587
435
|
else {
|
|
588
436
|
//console.log("right child")
|
|
589
437
|
s = p.left;
|
|
590
|
-
if (s.left && s.left.
|
|
591
|
-
//console.log("case 1: left sibling child red", p.value, p.
|
|
438
|
+
if (s.left && s.left.color === RED) {
|
|
439
|
+
//console.log("case 1: left sibling child red", p.value, p.color)
|
|
592
440
|
s = p.left = cloneNode(s);
|
|
593
441
|
z = s.left = cloneNode(s.left);
|
|
594
442
|
p.left = s.right;
|
|
595
443
|
s.right = p;
|
|
596
444
|
s.left = z;
|
|
597
|
-
s.
|
|
598
|
-
n.
|
|
599
|
-
p.
|
|
600
|
-
z.
|
|
445
|
+
s.color = p.color;
|
|
446
|
+
n.color = BLACK;
|
|
447
|
+
p.color = BLACK;
|
|
448
|
+
z.color = BLACK;
|
|
601
449
|
if (i > 1) {
|
|
602
|
-
|
|
450
|
+
const pp = stack[i - 2];
|
|
603
451
|
if (pp.right === p) {
|
|
604
452
|
pp.right = s;
|
|
605
453
|
}
|
|
@@ -610,7 +458,7 @@ function fixDoubleBlack(stack) {
|
|
|
610
458
|
stack[i - 1] = s;
|
|
611
459
|
return;
|
|
612
460
|
}
|
|
613
|
-
else if (s.right && s.right.
|
|
461
|
+
else if (s.right && s.right.color === RED) {
|
|
614
462
|
//console.log("case 1: right sibling child red")
|
|
615
463
|
s = p.left = cloneNode(s);
|
|
616
464
|
z = s.right = cloneNode(s.right);
|
|
@@ -618,12 +466,12 @@ function fixDoubleBlack(stack) {
|
|
|
618
466
|
s.right = z.left;
|
|
619
467
|
z.right = p;
|
|
620
468
|
z.left = s;
|
|
621
|
-
z.
|
|
622
|
-
p.
|
|
623
|
-
s.
|
|
624
|
-
n.
|
|
469
|
+
z.color = p.color;
|
|
470
|
+
p.color = BLACK;
|
|
471
|
+
s.color = BLACK;
|
|
472
|
+
n.color = BLACK;
|
|
625
473
|
if (i > 1) {
|
|
626
|
-
|
|
474
|
+
const pp = stack[i - 2];
|
|
627
475
|
if (pp.right === p) {
|
|
628
476
|
pp.right = z;
|
|
629
477
|
}
|
|
@@ -634,10 +482,10 @@ function fixDoubleBlack(stack) {
|
|
|
634
482
|
stack[i - 1] = z;
|
|
635
483
|
return;
|
|
636
484
|
}
|
|
637
|
-
if (s.
|
|
638
|
-
if (p.
|
|
485
|
+
if (s.color === BLACK) {
|
|
486
|
+
if (p.color === RED) {
|
|
639
487
|
//console.log("case 2: black sibling, red parent")
|
|
640
|
-
p.
|
|
488
|
+
p.color = BLACK;
|
|
641
489
|
p.left = repaint(RED, s);
|
|
642
490
|
return;
|
|
643
491
|
}
|
|
@@ -652,10 +500,10 @@ function fixDoubleBlack(stack) {
|
|
|
652
500
|
s = cloneNode(s);
|
|
653
501
|
p.left = s.right;
|
|
654
502
|
s.right = p;
|
|
655
|
-
s.
|
|
656
|
-
p.
|
|
503
|
+
s.color = p.color;
|
|
504
|
+
p.color = RED;
|
|
657
505
|
if (i > 1) {
|
|
658
|
-
|
|
506
|
+
const pp = stack[i - 2];
|
|
659
507
|
if (pp.right === p) {
|
|
660
508
|
pp.right = s;
|
|
661
509
|
}
|
|
@@ -676,236 +524,127 @@ function fixDoubleBlack(stack) {
|
|
|
676
524
|
}
|
|
677
525
|
}
|
|
678
526
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
var cstack = new Array(stack.length);
|
|
687
|
-
var n = stack[stack.length - 1];
|
|
688
|
-
cstack[cstack.length - 1] = new RBNode(n._color, n.key, n.value, n.left, n.right);
|
|
689
|
-
for (var i = stack.length - 2; i >= 0; --i) {
|
|
690
|
-
var n = stack[i];
|
|
691
|
-
if (n.left === stack[i + 1]) {
|
|
692
|
-
cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i + 1], n.right);
|
|
693
|
-
}
|
|
694
|
-
else {
|
|
695
|
-
cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i + 1]);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
//Get node
|
|
699
|
-
n = cstack[cstack.length - 1];
|
|
700
|
-
//console.log("start remove: ", n.value)
|
|
701
|
-
//If not leaf, then swap with previous node
|
|
702
|
-
if (n.left && n.right) {
|
|
703
|
-
//console.log("moving to leaf")
|
|
704
|
-
//First walk to previous leaf
|
|
705
|
-
var split = cstack.length;
|
|
706
|
-
n = n.left;
|
|
707
|
-
while (n.right) {
|
|
708
|
-
cstack.push(n);
|
|
709
|
-
n = n.right;
|
|
710
|
-
}
|
|
711
|
-
//Copy path to leaf
|
|
712
|
-
var v = cstack[split - 1];
|
|
713
|
-
cstack.push(new RBNode(n._color, v.key, v.value, n.left, n.right));
|
|
714
|
-
cstack[split - 1].key = n.key;
|
|
715
|
-
cstack[split - 1].value = n.value;
|
|
716
|
-
//Fix up stack
|
|
717
|
-
for (var i = cstack.length - 2; i >= split; --i) {
|
|
718
|
-
n = cstack[i];
|
|
719
|
-
cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i + 1]);
|
|
720
|
-
}
|
|
721
|
-
cstack[split - 1].left = cstack[split];
|
|
527
|
+
/** Iterates through the nodes in a red-black tree. */
|
|
528
|
+
export class RedBlackTreeIterator {
|
|
529
|
+
constructor(
|
|
530
|
+
/** The tree associated with the iterator. */
|
|
531
|
+
tree, stack) {
|
|
532
|
+
this.tree = tree;
|
|
533
|
+
this.stack = stack;
|
|
722
534
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
if (
|
|
731
|
-
|
|
535
|
+
/**
|
|
536
|
+
* Removes the iterator's current item form the tree.
|
|
537
|
+
*
|
|
538
|
+
* @returns A new binary search tree with the item removed.
|
|
539
|
+
*/
|
|
540
|
+
remove() {
|
|
541
|
+
const stack = this.stack;
|
|
542
|
+
if (stack.length === 0) {
|
|
543
|
+
return this.tree;
|
|
732
544
|
}
|
|
733
|
-
|
|
734
|
-
|
|
545
|
+
//First copy path to node
|
|
546
|
+
const cstack = new Array(stack.length);
|
|
547
|
+
let n = stack[stack.length - 1];
|
|
548
|
+
cstack[cstack.length - 1] = new RBNode(n.color, n.key, n.value, n.left, n.right);
|
|
549
|
+
let i;
|
|
550
|
+
for (i = stack.length - 2; i >= 0; --i) {
|
|
551
|
+
n = stack[i];
|
|
552
|
+
if (n.left === stack[i + 1]) {
|
|
553
|
+
cstack[i] = new RBNode(n.color, n.key, n.value, cstack[i + 1], n.right);
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
cstack[i] = new RBNode(n.color, n.key, n.value, n.left, cstack[i + 1]);
|
|
557
|
+
}
|
|
735
558
|
}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
if (n.left
|
|
741
|
-
//
|
|
742
|
-
//
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
}
|
|
749
|
-
//
|
|
750
|
-
|
|
751
|
-
|
|
559
|
+
//Get node
|
|
560
|
+
n = cstack[cstack.length - 1];
|
|
561
|
+
//console.log("start remove: ", n.value)
|
|
562
|
+
//If not leaf, then swap with previous node
|
|
563
|
+
if (n.left && n.right) {
|
|
564
|
+
//console.log("moving to leaf")
|
|
565
|
+
//First walk to previous leaf
|
|
566
|
+
const split = cstack.length;
|
|
567
|
+
n = n.left;
|
|
568
|
+
while (n.right) {
|
|
569
|
+
cstack.push(n);
|
|
570
|
+
n = n.right;
|
|
571
|
+
}
|
|
572
|
+
//Copy path to leaf
|
|
573
|
+
const v = cstack[split - 1];
|
|
574
|
+
cstack.push(new RBNode(n.color, v.key, v.value, n.left, n.right));
|
|
575
|
+
cstack[split - 1].key = n.key;
|
|
576
|
+
cstack[split - 1].value = n.value;
|
|
577
|
+
//Fix up stack
|
|
578
|
+
for (i = cstack.length - 2; i >= split; --i) {
|
|
579
|
+
n = cstack[i];
|
|
580
|
+
cstack[i] = new RBNode(n.color, n.key, n.value, n.left, cstack[i + 1]);
|
|
581
|
+
}
|
|
582
|
+
cstack[split - 1].left = cstack[split];
|
|
752
583
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
584
|
+
//console.log("stack=", cstack.map(function(v) { return v.value }))
|
|
585
|
+
//Remove leaf node
|
|
586
|
+
n = cstack[cstack.length - 1];
|
|
587
|
+
if (n.color === RED) {
|
|
588
|
+
//Easy case: removing red leaf
|
|
589
|
+
//console.log("RED leaf")
|
|
590
|
+
const p = cstack[cstack.length - 2];
|
|
591
|
+
if (p.left === n) {
|
|
592
|
+
p.left = null;
|
|
593
|
+
}
|
|
594
|
+
else if (p.right === n) {
|
|
595
|
+
p.right = null;
|
|
596
|
+
}
|
|
597
|
+
cstack.pop();
|
|
598
|
+
return new RedBlackTree(this.tree.compare, cstack[0]);
|
|
757
599
|
}
|
|
758
600
|
else {
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
601
|
+
if (n.left || n.right) {
|
|
602
|
+
//Second easy case: Single child black parent
|
|
603
|
+
//console.log("BLACK single child")
|
|
604
|
+
if (n.left) {
|
|
605
|
+
swapNode(n, n.left);
|
|
606
|
+
}
|
|
607
|
+
else if (n.right) {
|
|
608
|
+
swapNode(n, n.right);
|
|
609
|
+
}
|
|
610
|
+
//Child must be red, so repaint it black to balance color
|
|
611
|
+
n.color = BLACK;
|
|
612
|
+
return new RedBlackTree(this.tree.compare, cstack[0]);
|
|
613
|
+
}
|
|
614
|
+
else if (cstack.length === 1) {
|
|
615
|
+
//Third easy case: root
|
|
616
|
+
//console.log("ROOT")
|
|
617
|
+
return new RedBlackTree(this.tree.compare, null);
|
|
766
618
|
}
|
|
767
619
|
else {
|
|
768
|
-
|
|
620
|
+
//Hard case: Repaint n, and then do some nasty stuff
|
|
621
|
+
//console.log("BLACK leaf no children")
|
|
622
|
+
const parent = cstack[cstack.length - 2];
|
|
623
|
+
fixDoubleBlack(cstack);
|
|
624
|
+
//Fix up links
|
|
625
|
+
if (parent.left === n) {
|
|
626
|
+
parent.left = null;
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
parent.right = null;
|
|
630
|
+
}
|
|
769
631
|
}
|
|
770
632
|
}
|
|
633
|
+
return new RedBlackTree(this.tree.compare, cstack[0]);
|
|
771
634
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
get: function () {
|
|
777
|
-
if (this._stack.length > 0) {
|
|
778
|
-
return this._stack[this._stack.length - 1].key;
|
|
635
|
+
/** The key of the iterator's current item. */
|
|
636
|
+
get key() {
|
|
637
|
+
if (this.stack.length > 0) {
|
|
638
|
+
return this.stack[this.stack.length - 1].key;
|
|
779
639
|
}
|
|
780
640
|
return;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
get: function () {
|
|
787
|
-
if (this._stack.length > 0) {
|
|
788
|
-
return this._stack[this._stack.length - 1].value;
|
|
641
|
+
}
|
|
642
|
+
/** The value of the iterator's current item. */
|
|
643
|
+
get value() {
|
|
644
|
+
if (this.stack.length > 0) {
|
|
645
|
+
return this.stack[this.stack.length - 1].value;
|
|
789
646
|
}
|
|
790
647
|
return;
|
|
791
|
-
}
|
|
792
|
-
enumerable: true,
|
|
793
|
-
});
|
|
794
|
-
// //Advances iterator to next element in list
|
|
795
|
-
// iproto.next = function () {
|
|
796
|
-
// var stack = this._stack;
|
|
797
|
-
// if (stack.length === 0) {
|
|
798
|
-
// return;
|
|
799
|
-
// }
|
|
800
|
-
// var n = stack[stack.length - 1];
|
|
801
|
-
// if (n.right) {
|
|
802
|
-
// n = n.right;
|
|
803
|
-
// while (n) {
|
|
804
|
-
// stack.push(n);
|
|
805
|
-
// n = n.left;
|
|
806
|
-
// }
|
|
807
|
-
// } else {
|
|
808
|
-
// stack.pop();
|
|
809
|
-
// while (stack.length > 0 && stack[stack.length - 1].right === n) {
|
|
810
|
-
// n = stack[stack.length - 1];
|
|
811
|
-
// stack.pop();
|
|
812
|
-
// }
|
|
813
|
-
// }
|
|
814
|
-
// };
|
|
815
|
-
// //Checks if iterator is at end of tree
|
|
816
|
-
// Object.defineProperty(iproto, "hasNext", {
|
|
817
|
-
// get: function () {
|
|
818
|
-
// var stack = this._stack;
|
|
819
|
-
// if (stack.length === 0) {
|
|
820
|
-
// return false;
|
|
821
|
-
// }
|
|
822
|
-
// if (stack[stack.length - 1].right) {
|
|
823
|
-
// return true;
|
|
824
|
-
// }
|
|
825
|
-
// for (var s = stack.length - 1; s > 0; --s) {
|
|
826
|
-
// if (stack[s - 1].left === stack[s]) {
|
|
827
|
-
// return true;
|
|
828
|
-
// }
|
|
829
|
-
// }
|
|
830
|
-
// return false;
|
|
831
|
-
// },
|
|
832
|
-
// });
|
|
833
|
-
// //Update value
|
|
834
|
-
// iproto.update = function (value) {
|
|
835
|
-
// var stack = this._stack;
|
|
836
|
-
// if (stack.length === 0) {
|
|
837
|
-
// throw new Error("Can't update empty node!");
|
|
838
|
-
// }
|
|
839
|
-
// var cstack = new Array(stack.length);
|
|
840
|
-
// var n = stack[stack.length - 1];
|
|
841
|
-
// cstack[cstack.length - 1] = new RBNode(
|
|
842
|
-
// n._color,
|
|
843
|
-
// n.key,
|
|
844
|
-
// value,
|
|
845
|
-
// n.left,
|
|
846
|
-
// n.right
|
|
847
|
-
// );
|
|
848
|
-
// for (var i = stack.length - 2; i >= 0; --i) {
|
|
849
|
-
// n = stack[i];
|
|
850
|
-
// if (n.left === stack[i + 1]) {
|
|
851
|
-
// cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i + 1], n.right);
|
|
852
|
-
// } else {
|
|
853
|
-
// cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i + 1]);
|
|
854
|
-
// }
|
|
855
|
-
// }
|
|
856
|
-
// return new RedBlackTree(this.tree._compare, cstack[0]);
|
|
857
|
-
// };
|
|
858
|
-
// //Moves iterator backward one element
|
|
859
|
-
// iproto.prev = function () {
|
|
860
|
-
// var stack = this._stack;
|
|
861
|
-
// if (stack.length === 0) {
|
|
862
|
-
// return;
|
|
863
|
-
// }
|
|
864
|
-
// var n = stack[stack.length - 1];
|
|
865
|
-
// if (n.left) {
|
|
866
|
-
// n = n.left;
|
|
867
|
-
// while (n) {
|
|
868
|
-
// stack.push(n);
|
|
869
|
-
// n = n.right;
|
|
870
|
-
// }
|
|
871
|
-
// } else {
|
|
872
|
-
// stack.pop();
|
|
873
|
-
// while (stack.length > 0 && stack[stack.length - 1].left === n) {
|
|
874
|
-
// n = stack[stack.length - 1];
|
|
875
|
-
// stack.pop();
|
|
876
|
-
// }
|
|
877
|
-
// }
|
|
878
|
-
// };
|
|
879
|
-
// //Checks if iterator is at start of tree
|
|
880
|
-
// Object.defineProperty(iproto, "hasPrev", {
|
|
881
|
-
// get: function () {
|
|
882
|
-
// var stack = this._stack;
|
|
883
|
-
// if (stack.length === 0) {
|
|
884
|
-
// return false;
|
|
885
|
-
// }
|
|
886
|
-
// if (stack[stack.length - 1].left) {
|
|
887
|
-
// return true;
|
|
888
|
-
// }
|
|
889
|
-
// for (var s = stack.length - 1; s > 0; --s) {
|
|
890
|
-
// if (stack[s - 1].right === stack[s]) {
|
|
891
|
-
// return true;
|
|
892
|
-
// }
|
|
893
|
-
// }
|
|
894
|
-
// return false;
|
|
895
|
-
// },
|
|
896
|
-
// });
|
|
897
|
-
// //Default comparison function
|
|
898
|
-
// function defaultCompare(a, b) {
|
|
899
|
-
// if (a < b) {
|
|
900
|
-
// return -1;
|
|
901
|
-
// }
|
|
902
|
-
// if (a > b) {
|
|
903
|
-
// return 1;
|
|
904
|
-
// }
|
|
905
|
-
// return 0;
|
|
906
|
-
// }
|
|
907
|
-
//Build a tree
|
|
908
|
-
function createRBTree(compare) {
|
|
909
|
-
return new RedBlackTree(compare, null);
|
|
648
|
+
}
|
|
910
649
|
}
|
|
911
650
|
//# sourceMappingURL=functional-red-black-tree.js.map
|