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,348 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
module.exports = createRBTree;
|
|
3
2
|
// Modified from https://github.com/mikolalysenko/functional-red-black-tree/blob/master/rbtree.js
|
|
4
3
|
// which is MIT Licensed, Copyright (c) 2013 Mikola Lysenko.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
//
|
|
5
|
+
// External types modified from
|
|
6
|
+
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/functional-red-black-tree/functional-red-black-tree-tests.ts
|
|
7
|
+
// which is MIT Licensed.
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.RedBlackTreeIterator = exports.RedBlackTree = exports.RBNode = void 0;
|
|
10
|
+
const RED = 0;
|
|
11
|
+
const BLACK = 1;
|
|
12
|
+
/**
|
|
13
|
+
* @private Only exported for tests.
|
|
14
|
+
*/
|
|
15
|
+
class RBNode {
|
|
16
|
+
constructor(color,
|
|
17
|
+
/** The key associated with the node. */
|
|
18
|
+
key,
|
|
19
|
+
/** The value associated with the node. */
|
|
20
|
+
value,
|
|
21
|
+
/** The left subtree of the node. */
|
|
22
|
+
left,
|
|
23
|
+
/** The right subtree of the node. */
|
|
24
|
+
right) {
|
|
25
|
+
this.color = color;
|
|
26
|
+
this.key = key;
|
|
27
|
+
this.value = value;
|
|
28
|
+
this.left = left;
|
|
29
|
+
this.right = right;
|
|
30
|
+
}
|
|
13
31
|
}
|
|
32
|
+
exports.RBNode = RBNode;
|
|
14
33
|
function cloneNode(node) {
|
|
15
|
-
return new RBNode(node.
|
|
34
|
+
return new RBNode(node.color, node.key, node.value, node.left, node.right);
|
|
16
35
|
}
|
|
17
36
|
function repaint(color, node) {
|
|
18
37
|
return new RBNode(color, node.key, node.value, node.left, node.right);
|
|
19
38
|
}
|
|
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
|
-
}
|
|
39
|
+
/** Represents a functional red-black tree. */
|
|
40
|
+
class RedBlackTree {
|
|
41
|
+
constructor(compare, root) {
|
|
42
|
+
this.compare = compare;
|
|
43
|
+
this.root = root;
|
|
64
44
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Creates an empty red-black tree.
|
|
47
|
+
*
|
|
48
|
+
* @param compare Comparison function, same semantics as array.sort().
|
|
49
|
+
* @returns An empty tree ordered by `compare`.
|
|
50
|
+
*/
|
|
51
|
+
static new(compare) {
|
|
52
|
+
return new RedBlackTree(compare, null);
|
|
73
53
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Creates a new tree with `key` set to `value`, overwriting any
|
|
56
|
+
* existing value.
|
|
57
|
+
*
|
|
58
|
+
* @param key The key of the item to insert.
|
|
59
|
+
* @param value The value of the item to insert.
|
|
60
|
+
* @returns A new tree with `key` set to `value`.
|
|
61
|
+
*/
|
|
62
|
+
set(key, value) {
|
|
63
|
+
const cmp = this.compare;
|
|
64
|
+
//Find point to insert/replace node
|
|
65
|
+
let n = this.root;
|
|
66
|
+
const n_stack = [];
|
|
67
|
+
const d_stack = [];
|
|
68
|
+
let d = 0;
|
|
69
|
+
while (n) {
|
|
70
|
+
d = cmp(key, n.key);
|
|
71
|
+
n_stack.push(n);
|
|
72
|
+
d_stack.push(d);
|
|
73
|
+
// If the keys are equivalent, skip straight to the replace = true case.
|
|
74
|
+
if (d === 0)
|
|
75
|
+
break;
|
|
76
|
+
else if (d < 0) {
|
|
77
|
+
n = n.left;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
n = n.right;
|
|
81
|
+
}
|
|
82
82
|
}
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
const replace = d === 0 && n_stack.length > 0;
|
|
84
|
+
if (replace) {
|
|
85
|
+
// The last node in the n_stack has key equivalent to `key`.
|
|
86
|
+
// Replace its entry without changing the tree structure.
|
|
87
|
+
const lastN = n_stack[n_stack.length - 1];
|
|
88
|
+
if (lastN.key === key && lastN.value === value)
|
|
89
|
+
return this;
|
|
90
|
+
n_stack[n_stack.length - 1] = new RBNode(lastN.color, key, value, lastN.left, lastN.right);
|
|
85
91
|
}
|
|
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;
|
|
92
|
+
else {
|
|
93
|
+
n_stack.push(new RBNode(RED, key, value, null, null));
|
|
96
94
|
}
|
|
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
|
-
}
|
|
95
|
+
//Rebuild path to leaf node
|
|
96
|
+
let s;
|
|
97
|
+
for (s = n_stack.length - 2; s >= 0; --s) {
|
|
98
|
+
n = n_stack[s];
|
|
99
|
+
if (d_stack[s] <= 0) {
|
|
100
|
+
n_stack[s] = new RBNode(n.color, n.key, n.value, n_stack[s + 1], n.right);
|
|
127
101
|
}
|
|
128
102
|
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
|
-
}
|
|
103
|
+
n_stack[s] = new RBNode(n.color, n.key, n.value, n.left, n_stack[s + 1]);
|
|
158
104
|
}
|
|
159
105
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
106
|
+
if (replace)
|
|
107
|
+
return new RedBlackTree(cmp, n_stack[0]);
|
|
108
|
+
//Rebalance tree using rotations
|
|
109
|
+
//console.log("start insert", key, d_stack)
|
|
110
|
+
for (s = n_stack.length - 1; s > 1; --s) {
|
|
111
|
+
const p = n_stack[s - 1];
|
|
112
|
+
n = n_stack[s];
|
|
113
|
+
if (p.color === BLACK || n.color === BLACK) {
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
const pp = n_stack[s - 2];
|
|
117
|
+
if (pp.left === p) {
|
|
118
|
+
if (p.left === n) {
|
|
119
|
+
const y = pp.right;
|
|
120
|
+
if (y && y.color === RED) {
|
|
121
|
+
//console.log("LLr")
|
|
122
|
+
p.color = BLACK;
|
|
123
|
+
pp.right = repaint(BLACK, y);
|
|
124
|
+
pp.color = RED;
|
|
125
|
+
s -= 1;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
//console.log("LLb")
|
|
129
|
+
pp.color = RED;
|
|
130
|
+
pp.left = p.right;
|
|
131
|
+
p.color = BLACK;
|
|
132
|
+
p.right = pp;
|
|
133
|
+
n_stack[s - 2] = p;
|
|
134
|
+
n_stack[s - 1] = n;
|
|
135
|
+
if (s >= 3) {
|
|
136
|
+
const ppp = n_stack[s - 3];
|
|
137
|
+
if (ppp.left === pp) {
|
|
138
|
+
ppp.left = p;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
ppp.right = p;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
169
146
|
}
|
|
170
147
|
else {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
148
|
+
const y = pp.right;
|
|
149
|
+
if (y && y.color === RED) {
|
|
150
|
+
//console.log("LRr")
|
|
151
|
+
p.color = BLACK;
|
|
152
|
+
pp.right = repaint(BLACK, y);
|
|
153
|
+
pp.color = RED;
|
|
154
|
+
s -= 1;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
//console.log("LRb")
|
|
158
|
+
p.right = n.left;
|
|
159
|
+
pp.color = RED;
|
|
160
|
+
pp.left = n.right;
|
|
161
|
+
n.color = BLACK;
|
|
162
|
+
n.left = p;
|
|
163
|
+
n.right = pp;
|
|
164
|
+
n_stack[s - 2] = n;
|
|
165
|
+
n_stack[s - 1] = p;
|
|
166
|
+
if (s >= 3) {
|
|
167
|
+
const ppp = n_stack[s - 3];
|
|
168
|
+
if (ppp.left === pp) {
|
|
169
|
+
ppp.left = n;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
ppp.right = n;
|
|
173
|
+
}
|
|
185
174
|
}
|
|
175
|
+
break;
|
|
186
176
|
}
|
|
187
|
-
break;
|
|
188
177
|
}
|
|
189
178
|
}
|
|
190
179
|
else {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
180
|
+
if (p.right === n) {
|
|
181
|
+
const y = pp.left;
|
|
182
|
+
if (y && y.color === RED) {
|
|
183
|
+
//console.log("RRr", y.key)
|
|
184
|
+
p.color = BLACK;
|
|
185
|
+
pp.left = repaint(BLACK, y);
|
|
186
|
+
pp.color = RED;
|
|
187
|
+
s -= 1;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
//console.log("RRb")
|
|
191
|
+
pp.color = RED;
|
|
192
|
+
pp.right = p.left;
|
|
193
|
+
p.color = BLACK;
|
|
194
|
+
p.left = pp;
|
|
195
|
+
n_stack[s - 2] = p;
|
|
196
|
+
n_stack[s - 1] = n;
|
|
197
|
+
if (s >= 3) {
|
|
198
|
+
const ppp = n_stack[s - 3];
|
|
199
|
+
if (ppp.right === pp) {
|
|
200
|
+
ppp.right = p;
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
ppp.left = p;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
198
208
|
}
|
|
199
209
|
else {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
210
|
+
const y = pp.left;
|
|
211
|
+
if (y && y.color === RED) {
|
|
212
|
+
//console.log("RLr")
|
|
213
|
+
p.color = BLACK;
|
|
214
|
+
pp.left = repaint(BLACK, y);
|
|
215
|
+
pp.color = RED;
|
|
216
|
+
s -= 1;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
//console.log("RLb")
|
|
220
|
+
p.left = n.right;
|
|
221
|
+
pp.color = RED;
|
|
222
|
+
pp.right = n.left;
|
|
223
|
+
n.color = BLACK;
|
|
224
|
+
n.right = p;
|
|
225
|
+
n.left = pp;
|
|
226
|
+
n_stack[s - 2] = n;
|
|
227
|
+
n_stack[s - 1] = p;
|
|
228
|
+
if (s >= 3) {
|
|
229
|
+
const ppp = n_stack[s - 3];
|
|
230
|
+
if (ppp.right === pp) {
|
|
231
|
+
ppp.right = n;
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
ppp.left = n;
|
|
235
|
+
}
|
|
216
236
|
}
|
|
237
|
+
break;
|
|
217
238
|
}
|
|
218
|
-
break;
|
|
219
239
|
}
|
|
220
240
|
}
|
|
221
241
|
}
|
|
242
|
+
//Return new tree
|
|
243
|
+
n_stack[0].color = BLACK;
|
|
244
|
+
return new RedBlackTree(cmp, n_stack[0]);
|
|
222
245
|
}
|
|
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;
|
|
246
|
+
/**
|
|
247
|
+
* Finds the last item in the tree whose key is <= `key`.
|
|
248
|
+
*
|
|
249
|
+
* @param key The key to search for.
|
|
250
|
+
* @returns An iterator at the given element.
|
|
251
|
+
*/
|
|
252
|
+
le(key) {
|
|
253
|
+
const cmp = this.compare;
|
|
254
|
+
let n = this.root;
|
|
255
|
+
const stack = [];
|
|
256
|
+
let last_ptr = 0;
|
|
257
|
+
while (n) {
|
|
258
|
+
const d = cmp(key, n.key);
|
|
259
|
+
stack.push(n);
|
|
260
|
+
if (d >= 0) {
|
|
261
|
+
last_ptr = stack.length;
|
|
262
|
+
}
|
|
263
|
+
if (d < 0) {
|
|
264
|
+
n = n.left;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
n = n.right;
|
|
268
|
+
}
|
|
404
269
|
}
|
|
270
|
+
stack.length = last_ptr;
|
|
271
|
+
return new RedBlackTreeIterator(this, stack);
|
|
405
272
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
273
|
+
/**
|
|
274
|
+
* @returns An iterator pointing to the first item in the tree with `key`, otherwise null.
|
|
275
|
+
*/
|
|
276
|
+
find(key) {
|
|
277
|
+
const cmp = this.compare;
|
|
278
|
+
let n = this.root;
|
|
279
|
+
const stack = [];
|
|
280
|
+
while (n) {
|
|
281
|
+
const d = cmp(key, n.key);
|
|
282
|
+
stack.push(n);
|
|
283
|
+
if (d === 0) {
|
|
284
|
+
return new RedBlackTreeIterator(this, stack);
|
|
285
|
+
}
|
|
286
|
+
if (d <= 0) {
|
|
287
|
+
n = n.left;
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
n = n.right;
|
|
291
|
+
}
|
|
425
292
|
}
|
|
293
|
+
return new RedBlackTreeIterator(this, []);
|
|
426
294
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
295
|
+
/**
|
|
296
|
+
* Removes the first item with `key` in the tree.
|
|
297
|
+
*
|
|
298
|
+
* @param key The key of the item to remove.
|
|
299
|
+
* @returns A new tree with the given item removed, if it exists.
|
|
300
|
+
*/
|
|
301
|
+
remove(key) {
|
|
302
|
+
const iter = this.find(key);
|
|
303
|
+
return iter.remove();
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Retrieves the value associated with `key`.
|
|
307
|
+
*
|
|
308
|
+
* @param key The key of the item to look up.
|
|
309
|
+
* @returns The value of the first node associated with `key`.
|
|
310
|
+
*/
|
|
311
|
+
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
312
|
+
get(key) {
|
|
313
|
+
const cmp = this.compare;
|
|
314
|
+
let n = this.root;
|
|
315
|
+
while (n) {
|
|
316
|
+
const d = cmp(key, n.key);
|
|
317
|
+
if (d === 0) {
|
|
318
|
+
return n.value;
|
|
319
|
+
}
|
|
320
|
+
if (d <= 0) {
|
|
321
|
+
n = n.left;
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
n = n.right;
|
|
325
|
+
}
|
|
448
326
|
}
|
|
327
|
+
return;
|
|
449
328
|
}
|
|
450
|
-
return;
|
|
451
|
-
};
|
|
452
|
-
//Iterator for red black tree
|
|
453
|
-
function RedBlackTreeIterator(tree, stack) {
|
|
454
|
-
this.tree = tree;
|
|
455
|
-
this._stack = stack;
|
|
456
329
|
}
|
|
457
|
-
|
|
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
|
-
// };
|
|
330
|
+
exports.RedBlackTree = RedBlackTree;
|
|
478
331
|
//Swaps two nodes
|
|
479
332
|
function swapNode(n, v) {
|
|
480
333
|
n.key = v.key;
|
|
481
334
|
n.value = v.value;
|
|
482
335
|
n.left = v.left;
|
|
483
336
|
n.right = v.right;
|
|
484
|
-
n.
|
|
337
|
+
n.color = v.color;
|
|
485
338
|
}
|
|
486
339
|
//Fix up a double black node in a tree
|
|
487
340
|
function fixDoubleBlack(stack) {
|
|
488
|
-
|
|
489
|
-
for (
|
|
341
|
+
let n, p, s, z;
|
|
342
|
+
for (let i = stack.length - 1; i >= 0; --i) {
|
|
490
343
|
n = stack[i];
|
|
491
344
|
if (i === 0) {
|
|
492
|
-
n.
|
|
345
|
+
n.color = BLACK;
|
|
493
346
|
return;
|
|
494
347
|
}
|
|
495
348
|
//console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key)
|
|
@@ -497,19 +350,19 @@ function fixDoubleBlack(stack) {
|
|
|
497
350
|
if (p.left === n) {
|
|
498
351
|
//console.log("left child")
|
|
499
352
|
s = p.right;
|
|
500
|
-
if (s.right && s.right.
|
|
353
|
+
if (s.right && s.right.color === RED) {
|
|
501
354
|
//console.log("case 1: right sibling child red")
|
|
502
355
|
s = p.right = cloneNode(s);
|
|
503
356
|
z = s.right = cloneNode(s.right);
|
|
504
357
|
p.right = s.left;
|
|
505
358
|
s.left = p;
|
|
506
359
|
s.right = z;
|
|
507
|
-
s.
|
|
508
|
-
n.
|
|
509
|
-
p.
|
|
510
|
-
z.
|
|
360
|
+
s.color = p.color;
|
|
361
|
+
n.color = BLACK;
|
|
362
|
+
p.color = BLACK;
|
|
363
|
+
z.color = BLACK;
|
|
511
364
|
if (i > 1) {
|
|
512
|
-
|
|
365
|
+
const pp = stack[i - 2];
|
|
513
366
|
if (pp.left === p) {
|
|
514
367
|
pp.left = s;
|
|
515
368
|
}
|
|
@@ -520,7 +373,7 @@ function fixDoubleBlack(stack) {
|
|
|
520
373
|
stack[i - 1] = s;
|
|
521
374
|
return;
|
|
522
375
|
}
|
|
523
|
-
else if (s.left && s.left.
|
|
376
|
+
else if (s.left && s.left.color === RED) {
|
|
524
377
|
//console.log("case 1: left sibling child red")
|
|
525
378
|
s = p.right = cloneNode(s);
|
|
526
379
|
z = s.left = cloneNode(s.left);
|
|
@@ -528,12 +381,12 @@ function fixDoubleBlack(stack) {
|
|
|
528
381
|
s.left = z.right;
|
|
529
382
|
z.left = p;
|
|
530
383
|
z.right = s;
|
|
531
|
-
z.
|
|
532
|
-
p.
|
|
533
|
-
s.
|
|
534
|
-
n.
|
|
384
|
+
z.color = p.color;
|
|
385
|
+
p.color = BLACK;
|
|
386
|
+
s.color = BLACK;
|
|
387
|
+
n.color = BLACK;
|
|
535
388
|
if (i > 1) {
|
|
536
|
-
|
|
389
|
+
const pp = stack[i - 2];
|
|
537
390
|
if (pp.left === p) {
|
|
538
391
|
pp.left = z;
|
|
539
392
|
}
|
|
@@ -544,10 +397,10 @@ function fixDoubleBlack(stack) {
|
|
|
544
397
|
stack[i - 1] = z;
|
|
545
398
|
return;
|
|
546
399
|
}
|
|
547
|
-
if (s.
|
|
548
|
-
if (p.
|
|
400
|
+
if (s.color === BLACK) {
|
|
401
|
+
if (p.color === RED) {
|
|
549
402
|
//console.log("case 2: black sibling, red parent", p.right.value)
|
|
550
|
-
p.
|
|
403
|
+
p.color = BLACK;
|
|
551
404
|
p.right = repaint(RED, s);
|
|
552
405
|
return;
|
|
553
406
|
}
|
|
@@ -562,10 +415,10 @@ function fixDoubleBlack(stack) {
|
|
|
562
415
|
s = cloneNode(s);
|
|
563
416
|
p.right = s.left;
|
|
564
417
|
s.left = p;
|
|
565
|
-
s.
|
|
566
|
-
p.
|
|
418
|
+
s.color = p.color;
|
|
419
|
+
p.color = RED;
|
|
567
420
|
if (i > 1) {
|
|
568
|
-
|
|
421
|
+
const pp = stack[i - 2];
|
|
569
422
|
if (pp.left === p) {
|
|
570
423
|
pp.left = s;
|
|
571
424
|
}
|
|
@@ -587,19 +440,19 @@ function fixDoubleBlack(stack) {
|
|
|
587
440
|
else {
|
|
588
441
|
//console.log("right child")
|
|
589
442
|
s = p.left;
|
|
590
|
-
if (s.left && s.left.
|
|
591
|
-
//console.log("case 1: left sibling child red", p.value, p.
|
|
443
|
+
if (s.left && s.left.color === RED) {
|
|
444
|
+
//console.log("case 1: left sibling child red", p.value, p.color)
|
|
592
445
|
s = p.left = cloneNode(s);
|
|
593
446
|
z = s.left = cloneNode(s.left);
|
|
594
447
|
p.left = s.right;
|
|
595
448
|
s.right = p;
|
|
596
449
|
s.left = z;
|
|
597
|
-
s.
|
|
598
|
-
n.
|
|
599
|
-
p.
|
|
600
|
-
z.
|
|
450
|
+
s.color = p.color;
|
|
451
|
+
n.color = BLACK;
|
|
452
|
+
p.color = BLACK;
|
|
453
|
+
z.color = BLACK;
|
|
601
454
|
if (i > 1) {
|
|
602
|
-
|
|
455
|
+
const pp = stack[i - 2];
|
|
603
456
|
if (pp.right === p) {
|
|
604
457
|
pp.right = s;
|
|
605
458
|
}
|
|
@@ -610,7 +463,7 @@ function fixDoubleBlack(stack) {
|
|
|
610
463
|
stack[i - 1] = s;
|
|
611
464
|
return;
|
|
612
465
|
}
|
|
613
|
-
else if (s.right && s.right.
|
|
466
|
+
else if (s.right && s.right.color === RED) {
|
|
614
467
|
//console.log("case 1: right sibling child red")
|
|
615
468
|
s = p.left = cloneNode(s);
|
|
616
469
|
z = s.right = cloneNode(s.right);
|
|
@@ -618,12 +471,12 @@ function fixDoubleBlack(stack) {
|
|
|
618
471
|
s.right = z.left;
|
|
619
472
|
z.right = p;
|
|
620
473
|
z.left = s;
|
|
621
|
-
z.
|
|
622
|
-
p.
|
|
623
|
-
s.
|
|
624
|
-
n.
|
|
474
|
+
z.color = p.color;
|
|
475
|
+
p.color = BLACK;
|
|
476
|
+
s.color = BLACK;
|
|
477
|
+
n.color = BLACK;
|
|
625
478
|
if (i > 1) {
|
|
626
|
-
|
|
479
|
+
const pp = stack[i - 2];
|
|
627
480
|
if (pp.right === p) {
|
|
628
481
|
pp.right = z;
|
|
629
482
|
}
|
|
@@ -634,10 +487,10 @@ function fixDoubleBlack(stack) {
|
|
|
634
487
|
stack[i - 1] = z;
|
|
635
488
|
return;
|
|
636
489
|
}
|
|
637
|
-
if (s.
|
|
638
|
-
if (p.
|
|
490
|
+
if (s.color === BLACK) {
|
|
491
|
+
if (p.color === RED) {
|
|
639
492
|
//console.log("case 2: black sibling, red parent")
|
|
640
|
-
p.
|
|
493
|
+
p.color = BLACK;
|
|
641
494
|
p.left = repaint(RED, s);
|
|
642
495
|
return;
|
|
643
496
|
}
|
|
@@ -652,10 +505,10 @@ function fixDoubleBlack(stack) {
|
|
|
652
505
|
s = cloneNode(s);
|
|
653
506
|
p.left = s.right;
|
|
654
507
|
s.right = p;
|
|
655
|
-
s.
|
|
656
|
-
p.
|
|
508
|
+
s.color = p.color;
|
|
509
|
+
p.color = RED;
|
|
657
510
|
if (i > 1) {
|
|
658
|
-
|
|
511
|
+
const pp = stack[i - 2];
|
|
659
512
|
if (pp.right === p) {
|
|
660
513
|
pp.right = s;
|
|
661
514
|
}
|
|
@@ -676,236 +529,128 @@ function fixDoubleBlack(stack) {
|
|
|
676
529
|
}
|
|
677
530
|
}
|
|
678
531
|
}
|
|
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];
|
|
532
|
+
/** Iterates through the nodes in a red-black tree. */
|
|
533
|
+
class RedBlackTreeIterator {
|
|
534
|
+
constructor(
|
|
535
|
+
/** The tree associated with the iterator. */
|
|
536
|
+
tree, stack) {
|
|
537
|
+
this.tree = tree;
|
|
538
|
+
this.stack = stack;
|
|
722
539
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
if (
|
|
731
|
-
|
|
540
|
+
/**
|
|
541
|
+
* Removes the iterator's current item form the tree.
|
|
542
|
+
*
|
|
543
|
+
* @returns A new binary search tree with the item removed.
|
|
544
|
+
*/
|
|
545
|
+
remove() {
|
|
546
|
+
const stack = this.stack;
|
|
547
|
+
if (stack.length === 0) {
|
|
548
|
+
return this.tree;
|
|
732
549
|
}
|
|
733
|
-
|
|
734
|
-
|
|
550
|
+
//First copy path to node
|
|
551
|
+
const cstack = new Array(stack.length);
|
|
552
|
+
let n = stack[stack.length - 1];
|
|
553
|
+
cstack[cstack.length - 1] = new RBNode(n.color, n.key, n.value, n.left, n.right);
|
|
554
|
+
let i;
|
|
555
|
+
for (i = stack.length - 2; i >= 0; --i) {
|
|
556
|
+
n = stack[i];
|
|
557
|
+
if (n.left === stack[i + 1]) {
|
|
558
|
+
cstack[i] = new RBNode(n.color, n.key, n.value, cstack[i + 1], n.right);
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
cstack[i] = new RBNode(n.color, n.key, n.value, n.left, cstack[i + 1]);
|
|
562
|
+
}
|
|
735
563
|
}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
if (n.left
|
|
741
|
-
//
|
|
742
|
-
//
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
}
|
|
749
|
-
//
|
|
750
|
-
|
|
751
|
-
|
|
564
|
+
//Get node
|
|
565
|
+
n = cstack[cstack.length - 1];
|
|
566
|
+
//console.log("start remove: ", n.value)
|
|
567
|
+
//If not leaf, then swap with previous node
|
|
568
|
+
if (n.left && n.right) {
|
|
569
|
+
//console.log("moving to leaf")
|
|
570
|
+
//First walk to previous leaf
|
|
571
|
+
const split = cstack.length;
|
|
572
|
+
n = n.left;
|
|
573
|
+
while (n.right) {
|
|
574
|
+
cstack.push(n);
|
|
575
|
+
n = n.right;
|
|
576
|
+
}
|
|
577
|
+
//Copy path to leaf
|
|
578
|
+
const v = cstack[split - 1];
|
|
579
|
+
cstack.push(new RBNode(n.color, v.key, v.value, n.left, n.right));
|
|
580
|
+
cstack[split - 1].key = n.key;
|
|
581
|
+
cstack[split - 1].value = n.value;
|
|
582
|
+
//Fix up stack
|
|
583
|
+
for (i = cstack.length - 2; i >= split; --i) {
|
|
584
|
+
n = cstack[i];
|
|
585
|
+
cstack[i] = new RBNode(n.color, n.key, n.value, n.left, cstack[i + 1]);
|
|
586
|
+
}
|
|
587
|
+
cstack[split - 1].left = cstack[split];
|
|
752
588
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
589
|
+
//console.log("stack=", cstack.map(function(v) { return v.value }))
|
|
590
|
+
//Remove leaf node
|
|
591
|
+
n = cstack[cstack.length - 1];
|
|
592
|
+
if (n.color === RED) {
|
|
593
|
+
//Easy case: removing red leaf
|
|
594
|
+
//console.log("RED leaf")
|
|
595
|
+
const p = cstack[cstack.length - 2];
|
|
596
|
+
if (p.left === n) {
|
|
597
|
+
p.left = null;
|
|
598
|
+
}
|
|
599
|
+
else if (p.right === n) {
|
|
600
|
+
p.right = null;
|
|
601
|
+
}
|
|
602
|
+
cstack.pop();
|
|
603
|
+
return new RedBlackTree(this.tree.compare, cstack[0]);
|
|
757
604
|
}
|
|
758
605
|
else {
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
606
|
+
if (n.left || n.right) {
|
|
607
|
+
//Second easy case: Single child black parent
|
|
608
|
+
//console.log("BLACK single child")
|
|
609
|
+
if (n.left) {
|
|
610
|
+
swapNode(n, n.left);
|
|
611
|
+
}
|
|
612
|
+
else if (n.right) {
|
|
613
|
+
swapNode(n, n.right);
|
|
614
|
+
}
|
|
615
|
+
//Child must be red, so repaint it black to balance color
|
|
616
|
+
n.color = BLACK;
|
|
617
|
+
return new RedBlackTree(this.tree.compare, cstack[0]);
|
|
618
|
+
}
|
|
619
|
+
else if (cstack.length === 1) {
|
|
620
|
+
//Third easy case: root
|
|
621
|
+
//console.log("ROOT")
|
|
622
|
+
return new RedBlackTree(this.tree.compare, null);
|
|
766
623
|
}
|
|
767
624
|
else {
|
|
768
|
-
|
|
625
|
+
//Hard case: Repaint n, and then do some nasty stuff
|
|
626
|
+
//console.log("BLACK leaf no children")
|
|
627
|
+
const parent = cstack[cstack.length - 2];
|
|
628
|
+
fixDoubleBlack(cstack);
|
|
629
|
+
//Fix up links
|
|
630
|
+
if (parent.left === n) {
|
|
631
|
+
parent.left = null;
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
parent.right = null;
|
|
635
|
+
}
|
|
769
636
|
}
|
|
770
637
|
}
|
|
638
|
+
return new RedBlackTree(this.tree.compare, cstack[0]);
|
|
771
639
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
get: function () {
|
|
777
|
-
if (this._stack.length > 0) {
|
|
778
|
-
return this._stack[this._stack.length - 1].key;
|
|
640
|
+
/** The key of the iterator's current item. */
|
|
641
|
+
get key() {
|
|
642
|
+
if (this.stack.length > 0) {
|
|
643
|
+
return this.stack[this.stack.length - 1].key;
|
|
779
644
|
}
|
|
780
645
|
return;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
get: function () {
|
|
787
|
-
if (this._stack.length > 0) {
|
|
788
|
-
return this._stack[this._stack.length - 1].value;
|
|
646
|
+
}
|
|
647
|
+
/** The value of the iterator's current item. */
|
|
648
|
+
get value() {
|
|
649
|
+
if (this.stack.length > 0) {
|
|
650
|
+
return this.stack[this.stack.length - 1].value;
|
|
789
651
|
}
|
|
790
652
|
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);
|
|
653
|
+
}
|
|
910
654
|
}
|
|
655
|
+
exports.RedBlackTreeIterator = RedBlackTreeIterator;
|
|
911
656
|
//# sourceMappingURL=functional-red-black-tree.js.map
|