@live-change/flatten-interval-tree 0.8.26

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.
Files changed (65) hide show
  1. package/.babelrc +8 -0
  2. package/.travis.yml +14 -0
  3. package/LICENSE +21 -0
  4. package/README.md +172 -0
  5. package/dist/main.cjs.js +799 -0
  6. package/dist/main.esm.js +794 -0
  7. package/dist/main.umd.js +805 -0
  8. package/docs/Interval.html +1609 -0
  9. package/docs/IntervalTree.html +1506 -0
  10. package/docs/classes_interval.js.html +173 -0
  11. package/docs/fonts/OpenSans-Bold-webfont.eot +0 -0
  12. package/docs/fonts/OpenSans-Bold-webfont.svg +1830 -0
  13. package/docs/fonts/OpenSans-Bold-webfont.woff +0 -0
  14. package/docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  15. package/docs/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
  16. package/docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  17. package/docs/fonts/OpenSans-Italic-webfont.eot +0 -0
  18. package/docs/fonts/OpenSans-Italic-webfont.svg +1830 -0
  19. package/docs/fonts/OpenSans-Italic-webfont.woff +0 -0
  20. package/docs/fonts/OpenSans-Light-webfont.eot +0 -0
  21. package/docs/fonts/OpenSans-Light-webfont.svg +1831 -0
  22. package/docs/fonts/OpenSans-Light-webfont.woff +0 -0
  23. package/docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  24. package/docs/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
  25. package/docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  26. package/docs/fonts/OpenSans-Regular-webfont.eot +0 -0
  27. package/docs/fonts/OpenSans-Regular-webfont.svg +1831 -0
  28. package/docs/fonts/OpenSans-Regular-webfont.woff +0 -0
  29. package/docs/fonts/OpenSans-Semibold-webfont.eot +0 -0
  30. package/docs/fonts/OpenSans-Semibold-webfont.svg +1830 -0
  31. package/docs/fonts/OpenSans-Semibold-webfont.ttf +0 -0
  32. package/docs/fonts/OpenSans-Semibold-webfont.woff +0 -0
  33. package/docs/fonts/OpenSans-SemiboldItalic-webfont.eot +0 -0
  34. package/docs/fonts/OpenSans-SemiboldItalic-webfont.svg +1830 -0
  35. package/docs/fonts/OpenSans-SemiboldItalic-webfont.ttf +0 -0
  36. package/docs/fonts/OpenSans-SemiboldItalic-webfont.woff +0 -0
  37. package/docs/index.html +197 -0
  38. package/docs/index.js.html +624 -0
  39. package/docs/interval.js.html +184 -0
  40. package/docs/intervalTree.js.html +624 -0
  41. package/docs/scripts/linenumber.js +25 -0
  42. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  43. package/docs/scripts/prettify/lang-css.js +2 -0
  44. package/docs/scripts/prettify/prettify.js +28 -0
  45. package/docs/styles/jsdoc-default.css +692 -0
  46. package/docs/styles/prettify-jsdoc.css +111 -0
  47. package/docs/styles/prettify-tomorrow.css +132 -0
  48. package/examples/browser/index.html +49 -0
  49. package/examples/create-react-app/package.json +15 -0
  50. package/examples/create-react-app/public/index.html +11 -0
  51. package/examples/create-react-app/src/App.js +38 -0
  52. package/examples/create-react-app/src/ComposersList.js +15 -0
  53. package/examples/create-react-app/src/index.js +5 -0
  54. package/examples/es6-module/index.html +50 -0
  55. package/examples/nodejs/index.js +23 -0
  56. package/index.d.ts +65 -0
  57. package/index.js +6 -0
  58. package/package.json +52 -0
  59. package/rollup.config.js +21 -0
  60. package/src/classes/interval.js +131 -0
  61. package/src/classes/intervalTree.js +564 -0
  62. package/src/classes/node.js +97 -0
  63. package/src/utils/constants.js +16 -0
  64. package/test/intervalTree.js +232 -0
  65. package/test/node.js +64 -0
@@ -0,0 +1,624 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <title>intervalTree.js - Documentation</title>
7
+
8
+ <script src="scripts/prettify/prettify.js"></script>
9
+ <script src="scripts/prettify/lang-css.js"></script>
10
+ <!--[if lt IE 9]>
11
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
12
+ <![endif]-->
13
+ <link type="text/css" rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
14
+ <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
15
+ <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
16
+ </head>
17
+ <body>
18
+
19
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
20
+ <label for="nav-trigger" class="navicon-button x">
21
+ <div class="navicon"></div>
22
+ </label>
23
+
24
+ <label for="nav-trigger" class="overlay"></label>
25
+
26
+ <nav>
27
+ <li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Interval.html">Interval</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Interval.html#.comparable_less_than">comparable_less_than</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Interval.html#.comparable_max">comparable_max</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Interval.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Interval.html#equal_to">equal_to</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Interval.html#intersect">intersect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Interval.html#less_than">less_than</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Interval.html#not_intersect">not_intersect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Interval.html#output">output</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="IntervalTree.html">IntervalTree</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="IntervalTree.html#exist">exist</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="IntervalTree.html#forEach">forEach</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="IntervalTree.html#insert">insert</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="IntervalTree.html#isEmpty">isEmpty</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="IntervalTree.html#map">map</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="IntervalTree.html#remove">remove</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="IntervalTree.html#search">search</a></span></li>
28
+ </nav>
29
+
30
+ <div id="main">
31
+
32
+ <h1 class="page-title">intervalTree.js</h1>
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+ <section>
41
+ <article>
42
+ <pre class="prettyprint source linenums"><code>/**
43
+ * Created by Alex Bol on 3/31/2017.
44
+ */
45
+ 'use strict';
46
+
47
+ import Node from './node.js';
48
+ import {RB_TREE_COLOR_RED, RB_TREE_COLOR_BLACK} from '../utils/constants.js';
49
+
50
+ // const nil_node = new Node();
51
+
52
+ /**
53
+ * Implementation of interval binary search tree &lt;br/>
54
+ * Interval tree stores items which are couples of {key:interval, value: value} &lt;br/>
55
+ * Interval is an object with high and low properties or simply pair [low,high] of numeric values &lt;br />
56
+ * @type {IntervalTree}
57
+ */
58
+ class IntervalTree {
59
+ /**
60
+ * Construct new empty instance of IntervalTree
61
+ */
62
+ constructor() {
63
+ this.root = null;
64
+ this.nil_node = new Node();
65
+ }
66
+
67
+ /**
68
+ * Returns number of items stored in the interval tree
69
+ * @returns {number}
70
+ */
71
+ get size() {
72
+ let count = 0;
73
+ this.tree_walk(this.root, () => count++);
74
+ return count;
75
+ }
76
+
77
+ /**
78
+ * Returns array of sorted keys in the ascending order
79
+ * @returns {Array}
80
+ */
81
+ get keys() {
82
+ let res = [];
83
+ this.tree_walk(this.root, (node) => res.push(
84
+ node.item.key.output ? node.item.key.output() : node.item.key
85
+ ));
86
+ return res;
87
+ }
88
+
89
+ /**
90
+ * Return array of values in the ascending keys order
91
+ * @returns {Array}
92
+ */
93
+ get values() {
94
+ let res = [];
95
+ this.tree_walk(this.root, (node) => res.push(node.item.value));
96
+ return res;
97
+ }
98
+
99
+ /**
100
+ * Returns array of items (&lt;key,value> pairs) in the ascended keys order
101
+ * @returns {Array}
102
+ */
103
+ get items() {
104
+ let res = [];
105
+ this.tree_walk(this.root, (node) => res.push({
106
+ key: node.item.key.output ? node.item.key.output() : node.item.key,
107
+ value: node.item.value
108
+ }));
109
+ return res;
110
+ }
111
+
112
+ /**
113
+ * Returns true if tree is empty
114
+ * @returns {boolean}
115
+ */
116
+ isEmpty() {
117
+ return (this.root == null || this.root == this.nil_node);
118
+ }
119
+
120
+ /**
121
+ * Insert new item into interval tree
122
+ * @param key - interval object or array of two numbers [low, high]
123
+ * @param value - value representing any object (optional)
124
+ * @returns {Node} - returns reference to inserted node as an object {key:interval, value: value}
125
+ */
126
+ insert(key, value = key) {
127
+ if (key === undefined) return;
128
+ let insert_node = new Node(key, value, this.nil_node, this.nil_node, null, RB_TREE_COLOR_RED);
129
+ this.tree_insert(insert_node);
130
+ this.recalc_max(insert_node);
131
+ return insert_node;
132
+ }
133
+
134
+ /**
135
+ * Returns true if item {key,value} exist in the tree
136
+ * @param key - interval correspondent to keys stored in the tree
137
+ * @param value - value object to be checked
138
+ * @returns {boolean} - true if item {key, value} exist in the tree, false otherwise
139
+ */
140
+ exist(key, value) {
141
+ let search_node = new Node(key, value);
142
+ return this.tree_search(this.root, search_node) ? true : false;
143
+ }
144
+
145
+ /**
146
+ * Remove entry {key, value} from the tree
147
+ * @param key - interval correspondent to keys stored in the tree
148
+ * @param value - - value object
149
+ * @returns {boolean} - true if item {key, value} deleted, false if not found
150
+ */
151
+ remove(key, value) {
152
+ let search_node = new Node(key, value);
153
+ let delete_node = this.tree_search(this.root, search_node);
154
+ if (delete_node) {
155
+ this.tree_delete(delete_node);
156
+ }
157
+ return delete_node;
158
+ }
159
+
160
+ /**
161
+ * Returns array of entry values which keys intersect with given interval &lt;br/>
162
+ * If no values stored in the tree, returns array of keys which intersect given interval
163
+ * @param interval - search interval, or array [low, high]
164
+ * @param outputMapperFn(value,key) - optional function that maps (value, key) to custom output
165
+ * @returns {Array}
166
+ */
167
+ search(interval, outputMapperFn = (value, key) => value ? value : key.output()) {
168
+ let search_node = new Node(interval);
169
+ let resp_nodes = [];
170
+ this.tree_search_interval(this.root, search_node, resp_nodes);
171
+ return resp_nodes.map(node => outputMapperFn(node.item.value, node.item.key))
172
+ }
173
+
174
+ /**
175
+ * Tree visitor. For each node implement a callback function. &lt;br/>
176
+ * Method calls a callback function with two parameters (key, value)
177
+ * @param visitor(key,value) - function to be called for each tree item
178
+ */
179
+ forEach(visitor) {
180
+ this.tree_walk(this.root, (node) => visitor(node.item.key, node.item.value));
181
+ }
182
+
183
+ /** Value Mapper. Walk through every node and map node value to another value
184
+ * @param callback(value, key) - function to be called for each tree item
185
+ */
186
+ map(callback) {
187
+ const tree = new IntervalTree();
188
+ this.tree_walk(this.root, (node) => tree.insert(node.item.key, callback(node.item.value, node.item.key)));
189
+ return tree;
190
+ }
191
+
192
+ recalc_max(node) {
193
+ let node_current = node;
194
+ while (node_current.parent != null) {
195
+ node_current.parent.update_max();
196
+ node_current = node_current.parent;
197
+ }
198
+ }
199
+
200
+ tree_insert(insert_node) {
201
+ let current_node = this.root;
202
+ let parent_node = null;
203
+
204
+ if (this.root == null || this.root == this.nil_node) {
205
+ this.root = insert_node;
206
+ }
207
+ else {
208
+ while (current_node != this.nil_node) {
209
+ parent_node = current_node;
210
+ if (insert_node.less_than(current_node)) {
211
+ current_node = current_node.left;
212
+ }
213
+ else {
214
+ current_node = current_node.right;
215
+ }
216
+ }
217
+
218
+ insert_node.parent = parent_node;
219
+
220
+ if (insert_node.less_than(parent_node)) {
221
+ parent_node.left = insert_node;
222
+ }
223
+ else {
224
+ parent_node.right = insert_node;
225
+ }
226
+ }
227
+
228
+ this.insert_fixup(insert_node);
229
+ }
230
+
231
+ // After insertion insert_node may have red-colored parent, and this is a single possible violation
232
+ // Go upwords to the root and re-color until violation will be resolved
233
+ insert_fixup(insert_node) {
234
+ let current_node;
235
+ let uncle_node;
236
+
237
+ current_node = insert_node;
238
+ while (current_node != this.root &amp;&amp; current_node.parent.color == RB_TREE_COLOR_RED) {
239
+ if (current_node.parent == current_node.parent.parent.left) { // parent is left child of grandfather
240
+ uncle_node = current_node.parent.parent.right; // right brother of parent
241
+ if (uncle_node.color == RB_TREE_COLOR_RED) { // Case 1. Uncle is red
242
+ // re-color father and uncle into black
243
+ current_node.parent.color = RB_TREE_COLOR_BLACK;
244
+ uncle_node.color = RB_TREE_COLOR_BLACK;
245
+ current_node.parent.parent.color = RB_TREE_COLOR_RED;
246
+ current_node = current_node.parent.parent;
247
+ }
248
+ else { // Case 2 &amp; 3. Uncle is black
249
+ if (current_node == current_node.parent.right) { // Case 2. Current if right child
250
+ // This case is transformed into Case 3.
251
+ current_node = current_node.parent;
252
+ this.rotate_left(current_node);
253
+ }
254
+ current_node.parent.color = RB_TREE_COLOR_BLACK; // Case 3. Current is left child.
255
+ // Re-color father and grandfather, rotate grandfather right
256
+ current_node.parent.parent.color = RB_TREE_COLOR_RED;
257
+ this.rotate_right(current_node.parent.parent);
258
+ }
259
+ }
260
+ else { // parent is right child of grandfather
261
+ uncle_node = current_node.parent.parent.left; // left brother of parent
262
+ if (uncle_node.color == RB_TREE_COLOR_RED) { // Case 4. Uncle is red
263
+ // re-color father and uncle into black
264
+ current_node.parent.color = RB_TREE_COLOR_BLACK;
265
+ uncle_node.color = RB_TREE_COLOR_BLACK;
266
+ current_node.parent.parent.color = RB_TREE_COLOR_RED;
267
+ current_node = current_node.parent.parent;
268
+ }
269
+ else {
270
+ if (current_node == current_node.parent.left) { // Case 5. Current is left child
271
+ // Transform into case 6
272
+ current_node = current_node.parent;
273
+ this.rotate_right(current_node);
274
+ }
275
+ current_node.parent.color = RB_TREE_COLOR_BLACK; // Case 6. Current is right child.
276
+ // Re-color father and grandfather, rotate grandfather left
277
+ current_node.parent.parent.color = RB_TREE_COLOR_RED;
278
+ this.rotate_left(current_node.parent.parent);
279
+ }
280
+ }
281
+ }
282
+
283
+ this.root.color = RB_TREE_COLOR_BLACK;
284
+ }
285
+
286
+ tree_delete(delete_node) {
287
+ let cut_node; // node to be cut - either delete_node or successor_node ("y" from 14.4)
288
+ let fix_node; // node to fix rb tree property ("x" from 14.4)
289
+
290
+ if (delete_node.left == this.nil_node || delete_node.right == this.nil_node) { // delete_node has less then 2 children
291
+ cut_node = delete_node;
292
+ }
293
+ else { // delete_node has 2 children
294
+ cut_node = this.tree_successor(delete_node);
295
+ }
296
+
297
+ // fix_node if single child of cut_node
298
+ if (cut_node.left != this.nil_node) {
299
+ fix_node = cut_node.left;
300
+ }
301
+ else {
302
+ fix_node = cut_node.right;
303
+ }
304
+
305
+ // remove cut_node from parent
306
+ /*if (fix_node != this.nil_node) {*/
307
+ fix_node.parent = cut_node.parent;
308
+ /*}*/
309
+
310
+ if (cut_node == this.root) {
311
+ this.root = fix_node;
312
+ }
313
+ else {
314
+ if (cut_node == cut_node.parent.left) {
315
+ cut_node.parent.left = fix_node;
316
+ }
317
+ else {
318
+ cut_node.parent.right = fix_node;
319
+ }
320
+ cut_node.parent.update_max(); // update max property of the parent
321
+ }
322
+
323
+ this.recalc_max(fix_node); // update max property upward from fix_node to root
324
+
325
+ // COPY DATA !!!
326
+ // Delete_node becomes cut_node, it means that we cannot hold reference
327
+ // to node in outer structure and we will have to delete by key, additional search need
328
+ if (cut_node != delete_node) {
329
+ delete_node.copy_data(cut_node);
330
+ delete_node.update_max(); // update max property of the cut node at the new place
331
+ this.recalc_max(delete_node); // update max property upward from delete_node to root
332
+ }
333
+
334
+ if (/*fix_node != this.nil_node &amp;&amp; */cut_node.color == RB_TREE_COLOR_BLACK) {
335
+ this.delete_fixup(fix_node);
336
+ }
337
+ }
338
+
339
+ delete_fixup(fix_node) {
340
+ let current_node = fix_node;
341
+ let brother_node;
342
+
343
+ while (current_node != this.root &amp;&amp; current_node.parent != null &amp;&amp; current_node.color == RB_TREE_COLOR_BLACK) {
344
+ if (current_node == current_node.parent.left) { // fix node is left child
345
+ brother_node = current_node.parent.right;
346
+ if (brother_node.color == RB_TREE_COLOR_RED) { // Case 1. Brother is red
347
+ brother_node.color = RB_TREE_COLOR_BLACK; // re-color brother
348
+ current_node.parent.color = RB_TREE_COLOR_RED; // re-color father
349
+ this.rotate_left(current_node.parent);
350
+ brother_node = current_node.parent.right; // update brother
351
+ }
352
+ // Derive to cases 2..4: brother is black
353
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK &amp;&amp;
354
+ brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 2: both nephews black
355
+ brother_node.color = RB_TREE_COLOR_RED; // re-color brother
356
+ current_node = current_node.parent; // continue iteration
357
+ }
358
+ else {
359
+ if (brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 3: left nephew red, right nephew black
360
+ brother_node.color = RB_TREE_COLOR_RED; // re-color brother
361
+ brother_node.left.color = RB_TREE_COLOR_BLACK; // re-color nephew
362
+ this.rotate_right(brother_node);
363
+ brother_node = current_node.parent.right; // update brother
364
+ // Derive to case 4: left nephew black, right nephew red
365
+ }
366
+ // case 4: left nephew black, right nephew red
367
+ brother_node.color = current_node.parent.color;
368
+ current_node.parent.color = RB_TREE_COLOR_BLACK;
369
+ brother_node.right.color = RB_TREE_COLOR_BLACK;
370
+ this.rotate_left(current_node.parent);
371
+ current_node = this.root; // exit from loop
372
+ }
373
+ }
374
+ else { // fix node is right child
375
+ brother_node = current_node.parent.left;
376
+ if (brother_node.color == RB_TREE_COLOR_RED) { // Case 1. Brother is red
377
+ brother_node.color = RB_TREE_COLOR_BLACK; // re-color brother
378
+ current_node.parent.color = RB_TREE_COLOR_RED; // re-color father
379
+ this.rotate_right(current_node.parent);
380
+ brother_node = current_node.parent.left; // update brother
381
+ }
382
+ // Go to cases 2..4
383
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK &amp;&amp;
384
+ brother_node.right.color == RB_TREE_COLOR_BLACK) { // case 2
385
+ brother_node.color = RB_TREE_COLOR_RED; // re-color brother
386
+ current_node = current_node.parent; // continue iteration
387
+ }
388
+ else {
389
+ if (brother_node.left.color == RB_TREE_COLOR_BLACK) { // case 3: right nephew red, left nephew black
390
+ brother_node.color = RB_TREE_COLOR_RED; // re-color brother
391
+ brother_node.right.color = RB_TREE_COLOR_BLACK; // re-color nephew
392
+ this.rotate_left(brother_node);
393
+ brother_node = current_node.parent.left; // update brother
394
+ // Derive to case 4: right nephew black, left nephew red
395
+ }
396
+ // case 4: right nephew black, left nephew red
397
+ brother_node.color = current_node.parent.color;
398
+ current_node.parent.color = RB_TREE_COLOR_BLACK;
399
+ brother_node.left.color = RB_TREE_COLOR_BLACK;
400
+ this.rotate_right(current_node.parent);
401
+ current_node = this.root; // force exit from loop
402
+ }
403
+ }
404
+ }
405
+
406
+ current_node.color = RB_TREE_COLOR_BLACK;
407
+ }
408
+
409
+ tree_search(node, search_node) {
410
+ if (node == null || node == this.nil_node)
411
+ return undefined;
412
+
413
+ if (search_node.equal_to(node)) {
414
+ return node;
415
+ }
416
+ if (search_node.less_than(node)) {
417
+ return this.tree_search(node.left, search_node);
418
+ }
419
+ else {
420
+ return this.tree_search(node.right, search_node);
421
+ }
422
+ }
423
+
424
+ // Original search_interval method; container res support push() insertion
425
+ // Search all intervals intersecting given one
426
+ tree_search_interval(node, search_node, res) {
427
+ if (node != null &amp;&amp; node != this.nil_node) {
428
+ // if (node->left != this.nil_node &amp;&amp; node->left->max >= low) {
429
+ if (node.left != this.nil_node &amp;&amp; !node.not_intersect_left_subtree(search_node)) {
430
+ this.tree_search_interval(node.left, search_node, res);
431
+ }
432
+ // if (low &lt;= node->high &amp;&amp; node->low &lt;= high) {
433
+ if (node.intersect(search_node)) {
434
+ res.push(node);
435
+ }
436
+ // if (node->right != this.nil_node &amp;&amp; node->low &lt;= high) {
437
+ if (node.right != this.nil_node &amp;&amp; !node.not_intersect_right_subtree(search_node)) {
438
+ this.tree_search_interval(node.right, search_node, res);
439
+ }
440
+ }
441
+ }
442
+
443
+ local_minimum(node) {
444
+ let node_min = node;
445
+ while (node_min.left != null &amp;&amp; node_min.left != this.nil_node) {
446
+ node_min = node_min.left;
447
+ }
448
+ return node_min;
449
+ }
450
+
451
+ // not in use
452
+ local_maximum(node) {
453
+ let node_max = node;
454
+ while (node_max.right != null &amp;&amp; node_max.right != this.nil_node) {
455
+ node_max = node_max.right;
456
+ }
457
+ return node_max;
458
+ }
459
+
460
+ tree_successor(node) {
461
+ let node_successor;
462
+ let current_node;
463
+ let parent_node;
464
+
465
+ if (node.right != this.nil_node) {
466
+ node_successor = this.local_minimum(node.right);
467
+ }
468
+ else {
469
+ current_node = node;
470
+ parent_node = node.parent;
471
+ while (parent_node != null &amp;&amp; parent_node.right == current_node) {
472
+ current_node = parent_node;
473
+ parent_node = parent_node.parent;
474
+ }
475
+ node_successor = parent_node;
476
+ }
477
+ return node_successor;
478
+ }
479
+
480
+ // | right-rotate(T,y) |
481
+ // y ---------------. x
482
+ // / \ / \
483
+ // x c left-rotate(T,x) a y
484
+ // / \ &lt;--------------- / \
485
+ // a b b c
486
+
487
+ rotate_left(x) {
488
+ let y = x.right;
489
+
490
+ x.right = y.left; // b goes to x.right
491
+
492
+ if (y.left != this.nil_node) {
493
+ y.left.parent = x; // x becomes parent of b
494
+ }
495
+ y.parent = x.parent; // move parent
496
+
497
+ if (x == this.root) {
498
+ this.root = y; // y becomes root
499
+ }
500
+ else { // y becomes child of x.parent
501
+ if (x == x.parent.left) {
502
+ x.parent.left = y;
503
+ }
504
+ else {
505
+ x.parent.right = y;
506
+ }
507
+ }
508
+ y.left = x; // x becomes left child of y
509
+ x.parent = y; // and y becomes parent of x
510
+
511
+ if (x != null &amp;&amp; x != this.nil_node) {
512
+ x.update_max();
513
+ }
514
+
515
+ y = x.parent;
516
+ if (y != null &amp;&amp; y != this.nil_node) {
517
+ y.update_max();
518
+ }
519
+ }
520
+
521
+ rotate_right(y) {
522
+ let x = y.left;
523
+
524
+ y.left = x.right; // b goes to y.left
525
+
526
+ if (x.right != this.nil_node) {
527
+ x.right.parent = y; // y becomes parent of b
528
+ }
529
+ x.parent = y.parent; // move parent
530
+
531
+ if (y == this.root) { // x becomes root
532
+ this.root = x;
533
+ }
534
+ else { // y becomes child of x.parent
535
+ if (y == y.parent.left) {
536
+ y.parent.left = x;
537
+ }
538
+ else {
539
+ y.parent.right = x;
540
+ }
541
+ }
542
+ x.right = y; // y becomes right child of x
543
+ y.parent = x; // and x becomes parent of y
544
+
545
+ if (y != null &amp;&amp; y != this.nil_node) {
546
+ y.update_max();
547
+ }
548
+
549
+ x = y.parent;
550
+ if (x != null &amp;&amp; x != this.nil_node) {
551
+ x.update_max();
552
+ }
553
+ }
554
+
555
+ tree_walk(node, action) {
556
+ if (node != null &amp;&amp; node != this.nil_node) {
557
+ this.tree_walk(node.left, action);
558
+ // arr.push(node.toArray());
559
+ action(node);
560
+ this.tree_walk(node.right, action);
561
+ }
562
+ }
563
+
564
+ /* Return true if all red nodes have exactly two black child nodes */
565
+ testRedBlackProperty() {
566
+ let res = true;
567
+ this.tree_walk(this.root, function (node) {
568
+ if (node.color == RB_TREE_COLOR_RED) {
569
+ if (!(node.left.color == RB_TREE_COLOR_BLACK &amp;&amp; node.right.color == RB_TREE_COLOR_BLACK)) {
570
+ res = false;
571
+ }
572
+ }
573
+ });
574
+ return res;
575
+ }
576
+
577
+ /* Throw error if not every path from root to bottom has same black height */
578
+ testBlackHeightProperty(node) {
579
+ let height = 0;
580
+ let heightLeft = 0;
581
+ let heightRight = 0;
582
+ if (node.color == RB_TREE_COLOR_BLACK) {
583
+ height++;
584
+ }
585
+ if (node.left != this.nil_node) {
586
+ heightLeft = this.testBlackHeightProperty(node.left);
587
+ }
588
+ else {
589
+ heightLeft = 1;
590
+ }
591
+ if (node.right != this.nil_node) {
592
+ heightRight = this.testBlackHeightProperty(node.right);
593
+ }
594
+ else {
595
+ heightRight = 1;
596
+ }
597
+ if (heightLeft != heightRight) {
598
+ throw new Error('Red-black height property violated');
599
+ }
600
+ height += heightLeft;
601
+ return height;
602
+ };
603
+ };
604
+
605
+ export default IntervalTree;
606
+ </code></pre>
607
+ </article>
608
+ </section>
609
+
610
+
611
+
612
+
613
+ </div>
614
+
615
+ <br class="clear">
616
+
617
+ <footer>
618
+ Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sat Mar 16 2019 12:06:26 GMT+0200 (Israel Standard Time) using the Minami theme.
619
+ </footer>
620
+
621
+ <script>prettyPrint();</script>
622
+ <script src="scripts/linenumber.js"></script>
623
+ </body>
624
+ </html>