@flatten-js/interval-tree
Version:
Interval search tree with TypeScript support
3 lines (2 loc) • 9.77 kB
JavaScript
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).IntervalTree={})}(this,function(t){"use strict";class e{constructor(t,e){this.low=t,this.high=e}get max(){return this.clone()}less_than(t){return this.low<t.low||this.low===t.low&&this.high<t.high}equal_to(t){return this.low===t.low&&this.high===t.high}intersect(t){return!this.not_intersect(t)}not_intersect(t){return this.high<t.low||t.high<this.low}merge(t){const e=void 0===this.low?t.low:this.low<t.low?this.low:t.low,r=void 0===this.high?t.high:this.high>t.high?this.high:t.high,i=this.clone();return i.low=e,i.high=r,i}output(){return[this.low,this.high]}comparable_less_than(t,e){return t<e}}class r extends e{clone(){return new r(this.low,this.high)}}class i extends e{constructor(t,e){super(t,e)}static pointLess(t,e){return t[0]<e[0]||t[0]===e[0]&&t[1]<e[1]}static pointEq(t,e){return t[0]===e[0]&&t[1]===e[1]}clone(){return new i(this.low,this.high)}less_than(t){const e=this.low,r=t.low;if(i.pointLess(e,r))return!0;if(i.pointEq(e,r)){const e=this.high,r=t.high;return i.pointLess(e,r)}return!1}equal_to(t){return i.pointEq(this.low,t.low)&&i.pointEq(this.high,t.high)}not_intersect(t){const e=i.pointLess(this.high,t.low),r=i.pointLess(t.high,this.low);return e||r}merge(t){const e=this.low,r=t.low,o=this.high,s=t.high,n=i.pointLess(e,r)?e:r,l=i.pointLess(o,s)?s:o;return new i(n,l)}comparable_less_than(t,e){return i.pointLess(t,e)}output(){return[this.low,this.high]}}class o{constructor(t,e,i=null,o=null,s=null,n=0){if(this.left=i,this.right=o,this.parent=s,this.color=n,this.item={key:void 0,values:[]},void 0!==e&&this.item.values.push(e),void 0!==t)if(Array.isArray(t)){const[e,i]=t;if(!Number.isNaN(e)&&!Number.isNaN(i)){let t=e,o=i;t>o&&([t,o]=[o,t]),this.item.key=new r(t,o)}}else this.item.key=t;this.max=this.item.key?this.item.key.max:void 0}isNil(){return void 0===this.item.key&&0===this.item.values.length&&null===this.left&&null===this.right&&0===this.color}requireKey(){if(!this.item.key)throw new Error("Node key is undefined (nil/sentinel). Operation is not applicable.");return this.item.key}less_than(t){const e=this.requireKey(),r=t.requireKey();return e.less_than(r)}_value_equal(t){const e=this.item.values[0],r=t.item.values[0];return e&&r&&e.equal_to?e.equal_to(r):e===r}equal_to(t){const e=this.requireKey(),r=t.requireKey();return e.equal_to(r)}intersect(t){const e=this.requireKey(),r=t.requireKey();return e.intersect(r)}copy_data(t){this.item.key=t.item.key,this.item.values=t.item.values.slice()}update_max(){this.max=this.item.key?this.item.key.max:void 0,this.right&&this.right.max&&(this.max=this.max?this.max.merge(this.right.max):this.right.max),this.left&&this.left.max&&(this.max=this.max?this.max.merge(this.left.max):this.left.max)}not_intersect_left_subtree(t){if(!this.left)return!0;const e=this.left.max?this.left.max.high:this.left.item.key.high,r=this.requireKey(),i=t.requireKey();return r.comparable_less_than(e,i.low)}not_intersect_right_subtree(t){if(!this.right)return!0;const e=this.right.max?this.right.max.low:this.right.item.key.low,r=this.requireKey(),i=t.requireKey();return r.comparable_less_than(i.high,e)}}class s{constructor(){this.root=null,this.nil_node=new o}get size(){let t=0;return this.tree_walk(this.root,e=>t+=e.item.values.length),t}get keys(){const t=[];return this.tree_walk(this.root,e=>t.push(e.item.key.output())),t}get values(){const t=[];return this.tree_walk(this.root,e=>{for(const r of e.item.values)t.push(r)}),t}get items(){const t=[];return this.tree_walk(this.root,e=>{const r=e.item.key.output();for(const i of e.item.values)t.push({key:r,value:i})}),t}isEmpty(){return null==this.root||this.root===this.nil_node}clear(){this.root=null}insert(t,e=t){if(void 0===t)return;const r=this.tree_search(this.root,new o(t));if(r)return r.item.values.push(e),r;const i=new o(t,e,this.nil_node,this.nil_node,null,1);return this.tree_insert(i),this.recalc_max(i),i}exist(t,e=t){const r=this.tree_search(this.root,new o(t));return!!r&&(arguments.length<2||e===t||r.item.values.some(t=>t&&t.equal_to?t.equal_to(e):t===e))}remove(t,e=t){const r=this.tree_search(this.root,new o(t));if(!r)return;if(arguments.length<2)return this.tree_delete(r),r;const i=r.item.values.findIndex(t=>t&&t.equal_to?t.equal_to(e):t===e);return i>=0?(r.item.values.splice(i,1),0===r.item.values.length&&this.tree_delete(r),r):void 0}search(t,e=(t,e)=>t===e?e.output():t){const r=new o(t),i=[];this.tree_search_interval(this.root,r,i);const s=[];for(const t of i)for(const r of t.item.values)s.push(e(r,t.item.key));return s}intersect_any(t){const e=new o(t);return this.tree_find_any_interval(this.root,e)}forEach(t){this.tree_walk(this.root,e=>{for(const r of e.item.values)t(e.item.key,r)})}map(t){const e=new s;return this.tree_walk(this.root,r=>{for(const i of r.item.values)e.insert(r.item.key,t(i,r.item.key))}),e}*iterate(t,e=(t,e)=>t===e?e.output():t){let r=null;for(t?r=this.tree_search_nearest_forward(this.root,new o(t)):this.root&&(r=this.local_minimum(this.root));r;){for(const t of r.item.values)yield e(t,r.item.key);r=this.tree_successor(r)}}recalc_max(t){let e=t;for(;null!=e.parent;)e.parent.update_max(),e=e.parent}tree_insert(t){let e=this.root,r=null;if(null==this.root||this.root===this.nil_node)this.root=t;else{for(;e!==this.nil_node;)r=e,e=t.less_than(e)?e.left:e.right;t.parent=r,t.less_than(r)?r.left=t:r.right=t}this.insert_fixup(t)}insert_fixup(t){let e,r;for(e=t;e!==this.root&&1===e.parent.color;)e.parent===e.parent.parent.left?(r=e.parent.parent.right,1===r.color?(e.parent.color=0,r.color=0,e.parent.parent.color=1,e=e.parent.parent):(e===e.parent.right&&(e=e.parent,this.rotate_left(e)),e.parent.color=0,e.parent.parent.color=1,this.rotate_right(e.parent.parent))):(r=e.parent.parent.left,1===r.color?(e.parent.color=0,r.color=0,e.parent.parent.color=1,e=e.parent.parent):(e===e.parent.left&&(e=e.parent,this.rotate_right(e)),e.parent.color=0,e.parent.parent.color=1,this.rotate_left(e.parent.parent)));this.root.color=0}tree_delete(t){let e,r;e=t.left===this.nil_node||t.right===this.nil_node?t:this.tree_successor(t),r=e.left!==this.nil_node?e.left:e.right,r.parent=e.parent,e===this.root?this.root=r:(e===e.parent.left?e.parent.left=r:e.parent.right=r,e.parent.update_max()),this.recalc_max(r),e!==t&&(t.copy_data(e),t.update_max(),this.recalc_max(t)),0===e.color&&this.delete_fixup(r)}delete_fixup(t){let e,r=t;for(;r!==this.root&&null!=r.parent&&0===r.color;)r===r.parent.left?(e=r.parent.right,1===e.color&&(e.color=0,r.parent.color=1,this.rotate_left(r.parent),e=r.parent.right),0===e.left.color&&0===e.right.color?(e.color=1,r=r.parent):(0===e.right.color&&(e.color=1,e.left.color=0,this.rotate_right(e),e=r.parent.right),e.color=r.parent.color,r.parent.color=0,e.right.color=0,this.rotate_left(r.parent),r=this.root)):(e=r.parent.left,1===e.color&&(e.color=0,r.parent.color=1,this.rotate_right(r.parent),e=r.parent.left),0===e.left.color&&0===e.right.color?(e.color=1,r=r.parent):(0===e.left.color&&(e.color=1,e.right.color=0,this.rotate_left(e),e=r.parent.left),e.color=r.parent.color,r.parent.color=0,e.left.color=0,this.rotate_right(r.parent),r=this.root));r.color=0}tree_search(t,e){if(null!=t&&t!==this.nil_node)return e.equal_to(t)?t:e.less_than(t)?this.tree_search(t.left,e):this.tree_search(t.right,e)}tree_search_nearest_forward(t,e){let r=null,i=t;for(;i&&i!==this.nil_node;)i.less_than(e)?i.intersect(e)?(r=i,i=i.left):i=i.right:(r&&!i.less_than(r)||(r=i),i=i.left);return r||null}tree_search_interval(t,e,r){null!=t&&t!==this.nil_node&&(t.left===this.nil_node||t.not_intersect_left_subtree(e)||this.tree_search_interval(t.left,e,r),t.intersect(e)&&r.push(t),t.right===this.nil_node||t.not_intersect_right_subtree(e)||this.tree_search_interval(t.right,e,r))}tree_find_any_interval(t,e){let r=!1;return null!=t&&t!==this.nil_node&&(t.left===this.nil_node||t.not_intersect_left_subtree(e)||(r=this.tree_find_any_interval(t.left,e)),r||(r=t.intersect(e)),r||t.right===this.nil_node||t.not_intersect_right_subtree(e)||(r=this.tree_find_any_interval(t.right,e))),r}local_minimum(t){let e=t;for(;null!=e.left&&e.left!==this.nil_node;)e=e.left;return e}local_maximum(t){let e=t;for(;null!=e.right&&e.right!==this.nil_node;)e=e.right;return e}tree_successor(t){let e,r,i;if(t.right!==this.nil_node)e=this.local_minimum(t.right);else{for(r=t,i=t.parent;null!=i&&i.right===r;)r=i,i=i.parent;e=i}return e}rotate_left(t){const e=t.right;t.right=e.left,e.left!==this.nil_node&&(e.left.parent=t),e.parent=t.parent,t===this.root?this.root=e:t===t.parent.left?t.parent.left=e:t.parent.right=e,e.left=t,t.parent=e,null!==t&&t!==this.nil_node&&t.update_max(),null!=e&&e!==this.nil_node&&e.update_max()}rotate_right(t){const e=t.left;t.left=e.right,e.right!==this.nil_node&&(e.right.parent=t),e.parent=t.parent,t===this.root?this.root=e:t===t.parent.left?t.parent.left=e:t.parent.right=e,e.right=t,t.parent=e,null!==t&&t!==this.nil_node&&t.update_max(),null!=e&&e!==this.nil_node&&e.update_max()}tree_walk(t,e){null!=t&&t!==this.nil_node&&(this.tree_walk(t.left,e),e(t),this.tree_walk(t.right,e))}testRedBlackProperty(){let t=!0;return this.tree_walk(this.root,function(e){1===e.color&&(0===e.left.color&&0===e.right.color||(t=!1))}),t}testBlackHeightProperty(t){let e=0,r=0,i=0;if(0===t.color&&e++,r=t.left!==this.nil_node?this.testBlackHeightProperty(t.left):1,i=t.right!==this.nil_node?this.testBlackHeightProperty(t.right):1,r!==i)throw new Error("Red-black height property violated");return e+=r,e}}t.Interval=r,t.Interval2D=i,t.IntervalBase=e,t.IntervalTree=s,t.Node=o,t.default=s,Object.defineProperty(t,"__esModule",{value:!0})});
//# sourceMappingURL=main.umd.js.map