ekylibre-cartography 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +3 -0
- data/Rakefile +10 -0
- data/app/assets/javascripts/cartography.coffee +535 -0
- data/app/assets/javascripts/cartography/base.coffee +11 -0
- data/app/assets/javascripts/cartography/controls.coffee +463 -0
- data/app/assets/javascripts/cartography/events.coffee +36 -0
- data/app/assets/javascripts/cartography/layers.coffee +127 -0
- data/app/assets/javascripts/cartography/layers/simple.coffee +37 -0
- data/app/assets/javascripts/cartography/leaflet/controls.coffee +420 -0
- data/app/assets/javascripts/cartography/leaflet/handlers.coffee +461 -0
- data/app/assets/javascripts/cartography/leaflet/i18n.coffee +31 -0
- data/app/assets/javascripts/cartography/leaflet/layers.coffee +60 -0
- data/app/assets/javascripts/cartography/leaflet/toolbars.coffee +450 -0
- data/app/assets/javascripts/cartography/patches.js +8 -0
- data/app/assets/javascripts/cartography/util.coffee +18 -0
- data/app/assets/javascripts/main.js +18 -0
- data/app/assets/stylesheets/cartography.css +86 -0
- data/app/helpers/cartography_helper.rb +55 -0
- data/lib/cartography.rb +1 -0
- data/lib/cartography/engine.rb +11 -0
- data/lib/cartography/version.rb +3 -0
- data/vendor/assets/components/d3-array/dist/d3-array.js +590 -0
- data/vendor/assets/components/d3-array/dist/d3-array.min.js +2 -0
- data/vendor/assets/components/geojson-equality/dist/geojson-equality.js +295 -0
- data/vendor/assets/components/geojson-equality/dist/geojson-equality.js.map +21 -0
- data/vendor/assets/components/geojson-equality/dist/geojson-equality.min.js +1 -0
- data/vendor/assets/components/leaflet-controlpanel/dist/leaflet.controlpanel.css +29 -0
- data/vendor/assets/components/leaflet-controlpanel/dist/leaflet.controlpanel.js +269 -0
- data/vendor/assets/components/leaflet-draw-cut/dist/leaflet.draw.cut.css +1 -0
- data/vendor/assets/components/leaflet-draw-cut/dist/leaflet.draw.cut.js +8 -0
- data/vendor/assets/components/leaflet-draw-merge/dist/leaflet.draw.merge.css +0 -0
- data/vendor/assets/components/leaflet-draw-merge/dist/leaflet.draw.merge.js +48026 -0
- data/vendor/assets/components/leaflet-draw/dist/leaflet.draw-src.css +326 -0
- data/vendor/assets/components/leaflet-draw/dist/leaflet.draw-src.js +4653 -0
- data/vendor/assets/components/leaflet-draw/dist/leaflet.draw-src.map +1 -0
- data/vendor/assets/components/leaflet-draw/dist/leaflet.draw.css +10 -0
- data/vendor/assets/components/leaflet-draw/dist/leaflet.draw.js +10 -0
- data/vendor/assets/components/leaflet-geographicutil/dist/leaflet.geographicutil.js +3220 -0
- data/vendor/assets/components/leaflet-reactive_measure/dist/reactive_measure.css +30 -0
- data/vendor/assets/components/leaflet-reactive_measure/dist/reactive_measure.js +3764 -0
- data/vendor/assets/components/leaflet/dist/leaflet-src.js +13609 -0
- data/vendor/assets/components/leaflet/dist/leaflet-src.js.map +1 -0
- data/vendor/assets/components/leaflet/dist/leaflet-src.map +1 -0
- data/vendor/assets/components/leaflet/dist/leaflet.css +632 -0
- data/vendor/assets/components/leaflet/dist/leaflet.js +5 -0
- data/vendor/assets/components/leaflet/dist/leaflet.js.map +1 -0
- data/vendor/assets/components/martinez-polygon-clipping/dist/martinez.min.js +9 -0
- data/vendor/assets/components/martinez-polygon-clipping/dist/martinez.umd.js +1716 -0
- data/vendor/assets/components/martinez-polygon-clipping/dist/martinez.umd.js.map +1 -0
- data/vendor/assets/components/polygon-clipping/dist/polygon-clipping.js +279 -0
- data/vendor/assets/components/polygon-clipping/dist/polygon-clipping.min.js +1 -0
- data/vendor/assets/components/rtree/dist/rtree.js +911 -0
- data/vendor/assets/components/rtree/dist/rtree.min.js +1 -0
- data/vendor/assets/components/splaytree/dist/splay.es6.js +765 -0
- data/vendor/assets/components/splaytree/dist/splay.es6.js.map +1 -0
- data/vendor/assets/components/splaytree/dist/splay.js +797 -0
- data/vendor/assets/components/splaytree/dist/splay.js.map +1 -0
- metadata +156 -0
@@ -0,0 +1 @@
|
|
1
|
+
!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.RTree=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(_dereq_,module,exports){"use strict";var rectangle=_dereq_("./rectangle");var bbox=function(ar,obj){if(obj&&obj.bbox){return{leaf:obj,x:obj.bbox[0],y:obj.bbox[1],w:obj.bbox[2]-obj.bbox[0],h:obj.bbox[3]-obj.bbox[1]}}var len=ar.length;var i=0;var a=new Array(len);while(i<len){a[i]=[ar[i][0],ar[i][1]];i++}var first=a[0];len=a.length;i=1;var temp={min:[].concat(first),max:[].concat(first)};while(i<len){if(a[i][0]<temp.min[0]){temp.min[0]=a[i][0]}else if(a[i][0]>temp.max[0]){temp.max[0]=a[i][0]}if(a[i][1]<temp.min[1]){temp.min[1]=a[i][1]}else if(a[i][1]>temp.max[1]){temp.max[1]=a[i][1]}i++}var out={x:temp.min[0],y:temp.min[1],w:temp.max[0]-temp.min[0],h:temp.max[1]-temp.min[1]};if(obj){out.leaf=obj}return out};var geoJSON={};geoJSON.point=function(obj,self){return self.insertSubtree({x:obj.geometry.coordinates[0],y:obj.geometry.coordinates[1],w:0,h:0,leaf:obj},self.root)};geoJSON.multiPointLineString=function(obj,self){return self.insertSubtree(bbox(obj.geometry.coordinates,obj),self.root)};geoJSON.multiLineStringPolygon=function(obj,self){return self.insertSubtree(bbox(Array.prototype.concat.apply([],obj.geometry.coordinates),obj),self.root)};geoJSON.multiPolygon=function(obj,self){return self.insertSubtree(bbox(Array.prototype.concat.apply([],Array.prototype.concat.apply([],obj.geometry.coordinates)),obj),self.root)};geoJSON.makeRec=function(obj){return rectangle(obj.x,obj.y,obj.w,obj.h)};geoJSON.geometryCollection=function(obj,self){if(obj.bbox){return self.insertSubtree({leaf:obj,x:obj.bbox[0],y:obj.bbox[1],w:obj.bbox[2]-obj.bbox[0],h:obj.bbox[3]-obj.bbox[1]},self.root)}var geos=obj.geometry.geometries;var i=0;var len=geos.length;var temp=[];var g;while(i<len){g=geos[i];switch(g.type){case"Point":temp.push(geoJSON.makeRec({x:g.coordinates[0],y:g.coordinates[1],w:0,h:0}));break;case"MultiPoint":temp.push(geoJSON.makeRec(bbox(g.coordinates)));break;case"LineString":temp.push(geoJSON.makeRec(bbox(g.coordinates)));break;case"MultiLineString":temp.push(geoJSON.makeRec(bbox(Array.prototype.concat.apply([],g.coordinates))));break;case"Polygon":temp.push(geoJSON.makeRec(bbox(Array.prototype.concat.apply([],g.coordinates))));break;case"MultiPolygon":temp.push(geoJSON.makeRec(bbox(Array.prototype.concat.apply([],Array.prototype.concat.apply([],g.coordinates)))));break;case"GeometryCollection":geos=geos.concat(g.geometries);len=geos.length;break}i++}var first=temp[0];i=1;len=temp.length;while(i<len){first.expand(temp[i]);i++}return self.insertSubtree({leaf:obj,x:first.x(),y:first.y(),h:first.h(),w:first.w()},self.root)};exports.geoJSON=function(prelim){var that=this;var features,feature;if(Array.isArray(prelim)){features=prelim.slice()}else if(prelim.features&&Array.isArray(prelim.features)){features=prelim.features.slice()}else if(prelim instanceof Object){features=[prelim]}else{throw"this isn't what we're looking for"}var len=features.length;var i=0;while(i<len){feature=features[i];if(feature.type==="Feature"){switch(feature.geometry.type){case"Point":geoJSON.point(feature,that);break;case"MultiPoint":geoJSON.multiPointLineString(feature,that);break;case"LineString":geoJSON.multiPointLineString(feature,that);break;case"MultiLineString":geoJSON.multiLineStringPolygon(feature,that);break;case"Polygon":geoJSON.multiLineStringPolygon(feature,that);break;case"MultiPolygon":geoJSON.multiPolygon(feature,that);break;case"GeometryCollection":geoJSON.geometryCollection(feature,that);break}}i++}};exports.bbox=function(){var x1,y1,x2,y2;switch(arguments.length){case 1:x1=arguments[0][0][0];y1=arguments[0][0][1];x2=arguments[0][1][0];y2=arguments[0][1][1];break;case 2:x1=arguments[0][0];y1=arguments[0][1];x2=arguments[1][0];y2=arguments[1][1];break;case 4:x1=arguments[0];y1=arguments[1];x2=arguments[2];y2=arguments[3];break}return this.search({x:x1,y:y1,w:x2-x1,h:y2-y1})}},{"./rectangle":3}],2:[function(_dereq_,module,exports){"use strict";var RTree=_dereq_("./rtree");var geojson=_dereq_("./geojson");RTree.prototype.bbox=geojson.bbox;RTree.prototype.geoJSON=geojson.geoJSON;RTree.Rectangle=_dereq_("./rectangle");module.exports=RTree},{"./geojson":1,"./rectangle":3,"./rtree":4}],3:[function(_dereq_,module,exports){"use strict";function Rectangle(x,y,w,h){if(!(this instanceof Rectangle)){return new Rectangle(x,y,w,h)}var x2,y2,p;if(x.x){w=x.w;h=x.h;y=x.y;if(x.w!==0&&!x.w&&x.x2){w=x.x2-x.x;h=x.y2-x.y}else{w=x.w;h=x.h}x=x.x;x2=x+w;y2=y+h;p=h+w?false:true}else{x2=x+w;y2=y+h;p=h+w?false:true}this.x1=this.x=function(){return x};this.y1=this.y=function(){return y};this.x2=function(){return x2};this.y2=function(){return y2};this.w=function(){return w};this.h=function(){return h};this.p=function(){return p};this.overlap=function(a){if(p||a.p()){return x<=a.x2()&&x2>=a.x()&&y<=a.y2()&&y2>=a.y()}return x<a.x2()&&x2>a.x()&&y<a.y2()&&y2>a.y()};this.expand=function(a){var nx,ny;var ax=a.x();var ay=a.y();var ax2=a.x2();var ay2=a.y2();if(x>ax){nx=ax}else{nx=x}if(y>ay){ny=ay}else{ny=y}if(x2>ax2){w=x2-nx}else{w=ax2-nx}if(y2>ay2){h=y2-ny}else{h=ay2-ny}x=nx;y=ny;return this}}Rectangle.overlapRectangle=function(a,b){if(a.h===0&&a.w===0||b.h===0&&b.w===0){return a.x<=b.x+b.w&&a.x+a.w>=b.x&&a.y<=b.y+b.h&&a.y+a.h>=b.y}else{return a.x<b.x+b.w&&a.x+a.w>b.x&&a.y<b.y+b.h&&a.y+a.h>b.y}};Rectangle.containsRectangle=function(a,b){return a.x+a.w<=b.x+b.w&&a.x>=b.x&&a.y+a.h<=b.y+b.h&&a.y>=b.y};Rectangle.expandRectangle=function(a,b){var nx,ny;var axw=a.x+a.w;var bxw=b.x+b.w;var ayh=a.y+a.h;var byh=b.y+b.h;if(a.x>b.x){nx=b.x}else{nx=a.x}if(a.y>b.y){ny=b.y}else{ny=a.y}if(axw>bxw){a.w=axw-nx}else{a.w=bxw-nx}if(ayh>byh){a.h=ayh-ny}else{a.h=byh-ny}a.x=nx;a.y=ny;return a};Rectangle.makeMBR=function(nodes,rect){if(!nodes.length){return{x:0,y:0,w:0,h:0}}rect=rect||{};rect.x=nodes[0].x;rect.y=nodes[0].y;rect.w=nodes[0].w;rect.h=nodes[0].h;for(var i=1,len=nodes.length;i<len;i++){Rectangle.expandRectangle(rect,nodes[i])}return rect};Rectangle.squarifiedRatio=function(l,w,fill){var lperi=(l+w)/2;var larea=l*w;var lgeo=larea/(lperi*lperi);return larea*fill/lgeo};module.exports=Rectangle},{}],4:[function(_dereq_,module,exports){"use strict";var rectangle=_dereq_("./rectangle");function RTree(width){if(!(this instanceof RTree)){return new RTree(width)}var minWidth=3;var maxWidth=6;if(!isNaN(width)){minWidth=Math.floor(width/2);maxWidth=width}var rootTree={x:0,y:0,w:0,h:0,id:"root",nodes:[]};this.root=rootTree;var flatten=function(tree){var todo=tree.slice();var done=[];var current;while(todo.length){current=todo.pop();if(current.nodes){todo=todo.concat(current.nodes)}else if(current.leaf){done.push(current)}}return done};var removeSubtree=function(rect,obj,root){var hitStack=[];var countStack=[];var retArray=[];var currentDepth=1;var tree,i,ltree;if(!rect||!rectangle.overlapRectangle(rect,root)){return retArray}var retObj={x:rect.x,y:rect.y,w:rect.w,h:rect.h,target:obj};countStack.push(root.nodes.length);hitStack.push(root);while(hitStack.length>0){tree=hitStack.pop();i=countStack.pop()-1;if("target"in retObj){while(i>=0){ltree=tree.nodes[i];if(rectangle.overlapRectangle(retObj,ltree)){if(retObj.target&&"leaf"in ltree&<ree.leaf===retObj.target||!retObj.target&&("leaf"in ltree||rectangle.containsRectangle(ltree,retObj))){if("nodes"in ltree){retArray=flatten(tree.nodes.splice(i,1))}else{retArray=tree.nodes.splice(i,1)}rectangle.makeMBR(tree.nodes,tree);delete retObj.target;break}else if("nodes"in ltree){currentDepth++;countStack.push(i);hitStack.push(tree);tree=ltree;i=ltree.nodes.length}}i--}}else if("nodes"in retObj){tree.nodes.splice(i+1,1);if(tree.nodes.length>0){rectangle.makeMBR(tree.nodes,tree)}for(var t=0;t<retObj.nodes.length;t++){insertSubtree(retObj.nodes[t],tree)}retObj.nodes=[];if(hitStack.length===0&&tree.nodes.length<=1){retObj.nodes=searchSubtree(tree,true,retObj.nodes,tree);tree.nodes=[];hitStack.push(tree);countStack.push(1)}else if(hitStack.length>0&&tree.nodes.length<minWidth){retObj.nodes=searchSubtree(tree,true,retObj.nodes,tree);tree.nodes=[]}else{delete retObj.nodes}}else{rectangle.makeMBR(tree.nodes,tree)}currentDepth-=1}return retArray};var chooseLeafSubtree=function(rect,root){var bestChoiceIndex=-1;var bestChoiceStack=[];var bestChoiceArea;var first=true;bestChoiceStack.push(root);var nodes=root.nodes;while(first||bestChoiceIndex!==-1){if(first){first=false}else{bestChoiceStack.push(nodes[bestChoiceIndex]);nodes=nodes[bestChoiceIndex].nodes;bestChoiceIndex=-1}for(var i=nodes.length-1;i>=0;i--){var ltree=nodes[i];if("leaf"in ltree){bestChoiceIndex=-1;break}var oldLRatio=rectangle.squarifiedRatio(ltree.w,ltree.h,ltree.nodes.length+1);var nw=Math.max(ltree.x+ltree.w,rect.x+rect.w)-Math.min(ltree.x,rect.x);var nh=Math.max(ltree.y+ltree.h,rect.y+rect.h)-Math.min(ltree.y,rect.y);var lratio=rectangle.squarifiedRatio(nw,nh,ltree.nodes.length+2);if(bestChoiceIndex<0||Math.abs(lratio-oldLRatio)<bestChoiceArea){bestChoiceArea=Math.abs(lratio-oldLRatio);bestChoiceIndex=i}}}return bestChoiceStack};var linearSplit=function(nodes){var n=pickLinear(nodes);while(nodes.length>0){pickNext(nodes,n[0],n[1])}return n};var pickNext=function(nodes,a,b){var areaA=rectangle.squarifiedRatio(a.w,a.h,a.nodes.length+1);var areaB=rectangle.squarifiedRatio(b.w,b.h,b.nodes.length+1);var highAreaDelta;var highAreaNode;var lowestGrowthGroup;for(var i=nodes.length-1;i>=0;i--){var l=nodes[i];var newAreaA={};newAreaA.x=Math.min(a.x,l.x);newAreaA.y=Math.min(a.y,l.y);newAreaA.w=Math.max(a.x+a.w,l.x+l.w)-newAreaA.x;newAreaA.h=Math.max(a.y+a.h,l.y+l.h)-newAreaA.y;var changeNewAreaA=Math.abs(rectangle.squarifiedRatio(newAreaA.w,newAreaA.h,a.nodes.length+2)-areaA);var newAreaB={};newAreaB.x=Math.min(b.x,l.x);newAreaB.y=Math.min(b.y,l.y);newAreaB.w=Math.max(b.x+b.w,l.x+l.w)-newAreaB.x;newAreaB.h=Math.max(b.y+b.h,l.y+l.h)-newAreaB.y;var changeNewAreaB=Math.abs(rectangle.squarifiedRatio(newAreaB.w,newAreaB.h,b.nodes.length+2)-areaB);if(!highAreaNode||!highAreaDelta||Math.abs(changeNewAreaB-changeNewAreaA)<highAreaDelta){highAreaNode=i;highAreaDelta=Math.abs(changeNewAreaB-changeNewAreaA);lowestGrowthGroup=changeNewAreaB<changeNewAreaA?b:a}}var tempNode=nodes.splice(highAreaNode,1)[0];if(a.nodes.length+nodes.length+1<=minWidth){a.nodes.push(tempNode);rectangle.expandRectangle(a,tempNode)}else if(b.nodes.length+nodes.length+1<=minWidth){b.nodes.push(tempNode);rectangle.expandRectangle(b,tempNode)}else{lowestGrowthGroup.nodes.push(tempNode);rectangle.expandRectangle(lowestGrowthGroup,tempNode)}};var pickLinear=function(nodes){var lowestHighX=nodes.length-1;var highestLowX=0;var lowestHighY=nodes.length-1;var highestLowY=0;var t1,t2;for(var i=nodes.length-2;i>=0;i--){var l=nodes[i];if(l.x>nodes[highestLowX].x){highestLowX=i}else if(l.x+l.w<nodes[lowestHighX].x+nodes[lowestHighX].w){lowestHighX=i}if(l.y>nodes[highestLowY].y){highestLowY=i}else if(l.y+l.h<nodes[lowestHighY].y+nodes[lowestHighY].h){lowestHighY=i}}var dx=Math.abs(nodes[lowestHighX].x+nodes[lowestHighX].w-nodes[highestLowX].x);var dy=Math.abs(nodes[lowestHighY].y+nodes[lowestHighY].h-nodes[highestLowY].y);if(dx>dy){if(lowestHighX>highestLowX){t1=nodes.splice(lowestHighX,1)[0];t2=nodes.splice(highestLowX,1)[0]}else{t2=nodes.splice(highestLowX,1)[0];t1=nodes.splice(lowestHighX,1)[0]}}else{if(lowestHighY>highestLowY){t1=nodes.splice(lowestHighY,1)[0];t2=nodes.splice(highestLowY,1)[0]}else{t2=nodes.splice(highestLowY,1)[0];t1=nodes.splice(lowestHighY,1)[0]}}return[{x:t1.x,y:t1.y,w:t1.w,h:t1.h,nodes:[t1]},{x:t2.x,y:t2.y,w:t2.w,h:t2.h,nodes:[t2]}]};var attachData=function(node,moreTree){node.nodes=moreTree.nodes;node.x=moreTree.x;node.y=moreTree.y;node.w=moreTree.w;node.h=moreTree.h;return node};var searchSubtree=function(rect,returnNode,returnArray,root){var hitStack=[];if(!rectangle.overlapRectangle(rect,root)){return returnArray}hitStack.push(root.nodes);while(hitStack.length>0){var nodes=hitStack.pop();for(var i=nodes.length-1;i>=0;i--){var ltree=nodes[i];if(rectangle.overlapRectangle(rect,ltree)){if("nodes"in ltree){hitStack.push(ltree.nodes)}else if("leaf"in ltree){if(!returnNode){returnArray.push(ltree.leaf)}else{returnArray.push(ltree)}}}}}return returnArray};var insertSubtree=function(node,root){var bc;if(root.nodes.length===0){root.x=node.x;root.y=node.y;root.w=node.w;root.h=node.h;root.nodes.push(node);return}var treeStack=chooseLeafSubtree(node,root);var retObj=node;var pbc;while(treeStack.length>0){if(bc&&"nodes"in bc&&bc.nodes.length===0){pbc=bc;bc=treeStack.pop();for(var t=0;t<bc.nodes.length;t++){if(bc.nodes[t]===pbc||bc.nodes[t].nodes.length===0){bc.nodes.splice(t,1);break}}}else{bc=treeStack.pop()}if("leaf"in retObj||"nodes"in retObj||Array.isArray(retObj)){if(Array.isArray(retObj)){for(var ai=0;ai<retObj.length;ai++){rectangle.expandRectangle(bc,retObj[ai])}bc.nodes=bc.nodes.concat(retObj)}else{rectangle.expandRectangle(bc,retObj);bc.nodes.push(retObj)}if(bc.nodes.length<=maxWidth){retObj={x:bc.x,y:bc.y,w:bc.w,h:bc.h}}else{var a=linearSplit(bc.nodes);retObj=a;if(treeStack.length<1){bc.nodes.push(a[0]);treeStack.push(bc);retObj=a[1]}}}else{rectangle.expandRectangle(bc,retObj);retObj={x:bc.x,y:bc.y,w:bc.w,h:bc.h}}}};this.insertSubtree=insertSubtree;this.getTree=function(){return rootTree};this.setTree=function(newTree,where){if(!where){where=rootTree}return attachData(where,newTree)};this.search=function(rect,returnNode,returnArray){returnArray=returnArray||[];return searchSubtree(rect,returnNode,returnArray,rootTree)};var removeArea=function(rect){var numberDeleted=1,retArray=[],deleted;while(numberDeleted>0){deleted=removeSubtree(rect,false,rootTree);numberDeleted=deleted.length;retArray=retArray.concat(deleted)}return retArray};var removeObj=function(rect,obj){var retArray=removeSubtree(rect,obj,rootTree);return retArray};this.remove=function(rect,obj){if(!obj||typeof obj==="function"){return removeArea(rect,obj)}else{return removeObj(rect,obj)}};this.insert=function(rect,obj){var retArray=insertSubtree({x:rect.x,y:rect.y,w:rect.w,h:rect.h,leaf:obj},rootTree);return retArray}}RTree.prototype.toJSON=function(printing){return JSON.stringify(this.root,false,printing)};RTree.fromJSON=function(json){var rt=new RTree;rt.setTree(JSON.parse(json));return rt};module.exports=RTree;if(typeof Array.isArray!=="function"){Array.isArray=function(a){return typeof a==="object"&&{}.toString.call(a)==="[object Array]"}}},{"./rectangle":3}]},{},[2])(2)});
|
@@ -0,0 +1,765 @@
|
|
1
|
+
/**
|
2
|
+
* splaytree v2.0.2
|
3
|
+
* Fast Splay tree for Node and browser
|
4
|
+
*
|
5
|
+
* @author Alexander Milevski <info@w8r.name>
|
6
|
+
* @license MIT
|
7
|
+
* @preserve
|
8
|
+
*/
|
9
|
+
|
10
|
+
/* follows "An implementation of top-down splaying"
|
11
|
+
* by D. Sleator <sleator@cs.cmu.edu> March 1992
|
12
|
+
*/
|
13
|
+
|
14
|
+
/**
|
15
|
+
* @typedef {*} Key
|
16
|
+
*/
|
17
|
+
|
18
|
+
|
19
|
+
/**
|
20
|
+
* @typedef {*} Value
|
21
|
+
*/
|
22
|
+
|
23
|
+
|
24
|
+
/**
|
25
|
+
* @typedef {function(node:Node):void} Visitor
|
26
|
+
*/
|
27
|
+
|
28
|
+
|
29
|
+
/**
|
30
|
+
* @typedef {function(a:Key, b:Key):number} Comparator
|
31
|
+
*/
|
32
|
+
|
33
|
+
|
34
|
+
/**
|
35
|
+
* @param {function(node:Node):string} NodePrinter
|
36
|
+
*/
|
37
|
+
|
38
|
+
|
39
|
+
/**
|
40
|
+
* @typedef {Object} Node
|
41
|
+
* @property {Key} Key
|
42
|
+
* @property {Value=} data
|
43
|
+
* @property {Node} left
|
44
|
+
* @property {Node} right
|
45
|
+
*/
|
46
|
+
|
47
|
+
class Node {
|
48
|
+
|
49
|
+
constructor (key, data) {
|
50
|
+
this.key = key;
|
51
|
+
this.data = data;
|
52
|
+
this.left = null;
|
53
|
+
this.right = null;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
function DEFAULT_COMPARE (a, b) { return a > b ? 1 : a < b ? -1 : 0; }
|
58
|
+
|
59
|
+
|
60
|
+
/**
|
61
|
+
* Simple top down splay, not requiring i to be in the tree t.
|
62
|
+
* @param {Key} i
|
63
|
+
* @param {Node?} t
|
64
|
+
* @param {Comparator} comparator
|
65
|
+
*/
|
66
|
+
function splay (i, t, comparator) {
|
67
|
+
if (t === null) return t;
|
68
|
+
let l, r, y;
|
69
|
+
const N = new Node();
|
70
|
+
l = r = N;
|
71
|
+
|
72
|
+
while (true) {
|
73
|
+
const cmp = comparator(i, t.key);
|
74
|
+
//if (i < t.key) {
|
75
|
+
if (cmp < 0) {
|
76
|
+
if (t.left === null) break;
|
77
|
+
//if (i < t.left.key) {
|
78
|
+
if (comparator(i, t.left.key) < 0) {
|
79
|
+
y = t.left; /* rotate right */
|
80
|
+
t.left = y.right;
|
81
|
+
y.right = t;
|
82
|
+
t = y;
|
83
|
+
if (t.left === null) break;
|
84
|
+
}
|
85
|
+
r.left = t; /* link right */
|
86
|
+
r = t;
|
87
|
+
t = t.left;
|
88
|
+
//} else if (i > t.key) {
|
89
|
+
} else if (cmp > 0) {
|
90
|
+
if (t.right === null) break;
|
91
|
+
//if (i > t.right.key) {
|
92
|
+
if (comparator(i, t.right.key) > 0) {
|
93
|
+
y = t.right; /* rotate left */
|
94
|
+
t.right = y.left;
|
95
|
+
y.left = t;
|
96
|
+
t = y;
|
97
|
+
if (t.right === null) break;
|
98
|
+
}
|
99
|
+
l.right = t; /* link left */
|
100
|
+
l = t;
|
101
|
+
t = t.right;
|
102
|
+
} else {
|
103
|
+
break;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
/* assemble */
|
107
|
+
l.right = t.left;
|
108
|
+
r.left = t.right;
|
109
|
+
t.left = N.right;
|
110
|
+
t.right = N.left;
|
111
|
+
return t;
|
112
|
+
}
|
113
|
+
|
114
|
+
|
115
|
+
/**
|
116
|
+
* @param {Key} i
|
117
|
+
* @param {Value} data
|
118
|
+
* @param {Comparator} comparator
|
119
|
+
* @param {Tree} tree
|
120
|
+
* @return {Node} root
|
121
|
+
*/
|
122
|
+
function insert (i, data, t, comparator, tree) {
|
123
|
+
const node = new Node(i, data);
|
124
|
+
|
125
|
+
tree._size++;
|
126
|
+
|
127
|
+
if (t === null) {
|
128
|
+
node.left = node.right = null;
|
129
|
+
return node;
|
130
|
+
}
|
131
|
+
|
132
|
+
t = splay(i, t, comparator);
|
133
|
+
const cmp = comparator(i, t.key);
|
134
|
+
if (cmp < 0) {
|
135
|
+
node.left = t.left;
|
136
|
+
node.right = t;
|
137
|
+
t.left = null;
|
138
|
+
} else if (cmp >= 0) {
|
139
|
+
node.right = t.right;
|
140
|
+
node.left = t;
|
141
|
+
t.right = null;
|
142
|
+
}
|
143
|
+
return node;
|
144
|
+
}
|
145
|
+
|
146
|
+
|
147
|
+
/**
|
148
|
+
* Insert i into the tree t, unless it's already there.
|
149
|
+
* @param {Key} i
|
150
|
+
* @param {Value} data
|
151
|
+
* @param {Comparator} comparator
|
152
|
+
* @param {Tree} tree
|
153
|
+
* @return {Node} root
|
154
|
+
*/
|
155
|
+
function add (i, data, t, comparator, tree) {
|
156
|
+
const node = new Node(i, data);
|
157
|
+
|
158
|
+
if (t === null) {
|
159
|
+
node.left = node.right = null;
|
160
|
+
tree._size++;
|
161
|
+
return node;
|
162
|
+
}
|
163
|
+
|
164
|
+
t = splay(i, t, comparator);
|
165
|
+
const cmp = comparator(i, t.key);
|
166
|
+
if (cmp === 0) return t;
|
167
|
+
else {
|
168
|
+
if (cmp < 0) {
|
169
|
+
node.left = t.left;
|
170
|
+
node.right = t;
|
171
|
+
t.left = null;
|
172
|
+
} else if (cmp > 0) {
|
173
|
+
node.right = t.right;
|
174
|
+
node.left = t;
|
175
|
+
t.right = null;
|
176
|
+
}
|
177
|
+
tree._size++;
|
178
|
+
return node;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
|
183
|
+
/**
|
184
|
+
* Deletes i from the tree if it's there
|
185
|
+
* @param {Key} i
|
186
|
+
* @param {Tree} tree
|
187
|
+
* @param {Comparator} comparator
|
188
|
+
* @param {Tree} tree
|
189
|
+
* @return {Node} new root
|
190
|
+
*/
|
191
|
+
function remove (i, t, comparator, tree) {
|
192
|
+
let x;
|
193
|
+
if (t === null) return null;
|
194
|
+
t = splay(i, t, comparator);
|
195
|
+
if (i === t.key) { /* found it */
|
196
|
+
if (t.left === null) {
|
197
|
+
x = t.right;
|
198
|
+
} else {
|
199
|
+
x = splay(i, t.left, comparator);
|
200
|
+
x.right = t.right;
|
201
|
+
}
|
202
|
+
tree._size--;
|
203
|
+
return x;
|
204
|
+
}
|
205
|
+
return t; /* It wasn't there */
|
206
|
+
}
|
207
|
+
|
208
|
+
|
209
|
+
function split (key, v, comparator) {
|
210
|
+
let left, right;
|
211
|
+
if (v === null) {
|
212
|
+
left = right = null;
|
213
|
+
} else {
|
214
|
+
v = splay(key, v, comparator);
|
215
|
+
|
216
|
+
const cmp = comparator(v.key, key);
|
217
|
+
if (cmp === 0) {
|
218
|
+
left = v.left;
|
219
|
+
right = v.right;
|
220
|
+
} else if (cmp < 0) {
|
221
|
+
right = v.right;
|
222
|
+
v.right = null;
|
223
|
+
left = v;
|
224
|
+
} else {
|
225
|
+
left = v.left;
|
226
|
+
v.left = null;
|
227
|
+
right = v;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
return { left, right };
|
231
|
+
}
|
232
|
+
|
233
|
+
|
234
|
+
function merge (left, right, comparator) {
|
235
|
+
if (right === null) return left;
|
236
|
+
if (left === null) return right;
|
237
|
+
|
238
|
+
right = splay(left.key, right, comparator);
|
239
|
+
right.left = left;
|
240
|
+
return right;
|
241
|
+
}
|
242
|
+
|
243
|
+
|
244
|
+
/**
|
245
|
+
* Prints level of the tree
|
246
|
+
* @param {Node} root
|
247
|
+
* @param {String} prefix
|
248
|
+
* @param {Boolean} isTail
|
249
|
+
* @param {Array<string>} out
|
250
|
+
* @param {Function(node:Node):String} printNode
|
251
|
+
*/
|
252
|
+
function printRow (root, prefix, isTail, out, printNode) {
|
253
|
+
if (root) {
|
254
|
+
out(`${ prefix }${ isTail ? '└── ' : '├── ' }${ printNode(root) }\n`);
|
255
|
+
const indent = prefix + (isTail ? ' ' : '│ ');
|
256
|
+
if (root.left) printRow(root.left, indent, false, out, printNode);
|
257
|
+
if (root.right) printRow(root.right, indent, true, out, printNode);
|
258
|
+
}
|
259
|
+
}
|
260
|
+
|
261
|
+
|
262
|
+
class Tree {
|
263
|
+
|
264
|
+
constructor (comparator = DEFAULT_COMPARE) {
|
265
|
+
this._comparator = comparator;
|
266
|
+
this._root = null;
|
267
|
+
this._size = 0;
|
268
|
+
}
|
269
|
+
|
270
|
+
|
271
|
+
/**
|
272
|
+
* Inserts a key, allows duplicates
|
273
|
+
* @param {Key} key
|
274
|
+
* @param {Value=} data
|
275
|
+
* @return {Node|null}
|
276
|
+
*/
|
277
|
+
insert (key, data) {
|
278
|
+
return this._root = insert(key, data, this._root, this._comparator, this);
|
279
|
+
}
|
280
|
+
|
281
|
+
|
282
|
+
/**
|
283
|
+
* Adds a key, if it is not present in the tree
|
284
|
+
* @param {Key} key
|
285
|
+
* @param {Value=} data
|
286
|
+
* @return {Node|null}
|
287
|
+
*/
|
288
|
+
add (key, data) {
|
289
|
+
return this._root = add(key, data, this._root, this._comparator, this);
|
290
|
+
}
|
291
|
+
|
292
|
+
|
293
|
+
/**
|
294
|
+
* @param {Key} key
|
295
|
+
* @return {Node|null}
|
296
|
+
*/
|
297
|
+
remove (key) {
|
298
|
+
this._root = remove(key, this._root, this._comparator, this);
|
299
|
+
}
|
300
|
+
|
301
|
+
|
302
|
+
/**
|
303
|
+
* Removes and returns the node with smallest key
|
304
|
+
* @return {?Node}
|
305
|
+
*/
|
306
|
+
pop () {
|
307
|
+
let node = this._root;
|
308
|
+
if (node) {
|
309
|
+
while (node.left) node = node.left;
|
310
|
+
this._root = splay(node.key, this._root, this._comparator);
|
311
|
+
this._root = remove(node.key, this._root, this._comparator, this);
|
312
|
+
return { key: node.key, data: node.data };
|
313
|
+
}
|
314
|
+
return null;
|
315
|
+
}
|
316
|
+
|
317
|
+
|
318
|
+
/**
|
319
|
+
* @param {Key} key
|
320
|
+
* @return {Node|null}
|
321
|
+
*/
|
322
|
+
findStatic (key) {
|
323
|
+
let current = this._root;
|
324
|
+
const compare = this._comparator;
|
325
|
+
while (current) {
|
326
|
+
const cmp = compare(key, current.key);
|
327
|
+
if (cmp === 0) return current;
|
328
|
+
else if (cmp < 0) current = current.left;
|
329
|
+
else current = current.right;
|
330
|
+
}
|
331
|
+
return null;
|
332
|
+
}
|
333
|
+
|
334
|
+
|
335
|
+
/**
|
336
|
+
* @param {Key} key
|
337
|
+
* @return {Node|null}
|
338
|
+
*/
|
339
|
+
find (key) {
|
340
|
+
if (this._root) {
|
341
|
+
this._root = splay(key, this._root, this._comparator);
|
342
|
+
if (this._comparator(key, this._root.key) !== 0) return null;
|
343
|
+
}
|
344
|
+
return this._root;
|
345
|
+
}
|
346
|
+
|
347
|
+
|
348
|
+
/**
|
349
|
+
* @param {Key} key
|
350
|
+
* @return {Boolean}
|
351
|
+
*/
|
352
|
+
contains (key) {
|
353
|
+
let current = this._root;
|
354
|
+
const compare = this._comparator;
|
355
|
+
while (current) {
|
356
|
+
const cmp = compare(key, current.key);
|
357
|
+
if (cmp === 0) return true;
|
358
|
+
else if (cmp < 0) current = current.left;
|
359
|
+
else current = current.right;
|
360
|
+
}
|
361
|
+
return false;
|
362
|
+
}
|
363
|
+
|
364
|
+
|
365
|
+
/**
|
366
|
+
* @param {Visitor} visitor
|
367
|
+
* @param {*=} ctx
|
368
|
+
* @return {SplayTree}
|
369
|
+
*/
|
370
|
+
forEach (visitor, ctx) {
|
371
|
+
let current = this._root;
|
372
|
+
const Q = []; /* Initialize stack s */
|
373
|
+
let done = false;
|
374
|
+
|
375
|
+
while (!done) {
|
376
|
+
if (current !== null) {
|
377
|
+
Q.push(current);
|
378
|
+
current = current.left;
|
379
|
+
} else {
|
380
|
+
if (Q.length !== 0) {
|
381
|
+
current = Q.pop();
|
382
|
+
visitor.call(ctx, current);
|
383
|
+
|
384
|
+
current = current.right;
|
385
|
+
} else done = true;
|
386
|
+
}
|
387
|
+
}
|
388
|
+
return this;
|
389
|
+
}
|
390
|
+
|
391
|
+
|
392
|
+
/**
|
393
|
+
* Walk key range from `low` to `high`. Stops if `fn` returns a value.
|
394
|
+
* @param {Key} low
|
395
|
+
* @param {Key} high
|
396
|
+
* @param {Function} fn
|
397
|
+
* @param {*?} ctx
|
398
|
+
* @return {SplayTree}
|
399
|
+
*/
|
400
|
+
range (low, high, fn, ctx) {
|
401
|
+
const Q = [];
|
402
|
+
const compare = this._comparator;
|
403
|
+
let node = this._root, cmp;
|
404
|
+
|
405
|
+
while (Q.length !== 0 || node) {
|
406
|
+
if (node) {
|
407
|
+
Q.push(node);
|
408
|
+
node = node.left;
|
409
|
+
} else {
|
410
|
+
node = Q.pop();
|
411
|
+
cmp = compare(node.key, high);
|
412
|
+
if (cmp > 0) {
|
413
|
+
break;
|
414
|
+
} else if (compare(node.key, low) >= 0) {
|
415
|
+
if (fn.call(ctx, node)) return this; // stop if smth is returned
|
416
|
+
}
|
417
|
+
node = node.right;
|
418
|
+
}
|
419
|
+
}
|
420
|
+
return this;
|
421
|
+
}
|
422
|
+
|
423
|
+
|
424
|
+
/**
|
425
|
+
* Returns array of keys
|
426
|
+
* @return {Array<Key>}
|
427
|
+
*/
|
428
|
+
keys () {
|
429
|
+
const keys = [];
|
430
|
+
this.forEach(({ key }) => keys.push(key));
|
431
|
+
return keys;
|
432
|
+
}
|
433
|
+
|
434
|
+
|
435
|
+
/**
|
436
|
+
* Returns array of all the data in the nodes
|
437
|
+
* @return {Array<Value>}
|
438
|
+
*/
|
439
|
+
values () {
|
440
|
+
const values = [];
|
441
|
+
this.forEach(({ data }) => values.push(data));
|
442
|
+
return values;
|
443
|
+
}
|
444
|
+
|
445
|
+
|
446
|
+
/**
|
447
|
+
* @return {Key|null}
|
448
|
+
*/
|
449
|
+
min() {
|
450
|
+
if (this._root) return this.minNode(this._root).key;
|
451
|
+
return null;
|
452
|
+
}
|
453
|
+
|
454
|
+
|
455
|
+
/**
|
456
|
+
* @return {Key|null}
|
457
|
+
*/
|
458
|
+
max() {
|
459
|
+
if (this._root) return this.maxNode(this._root).key;
|
460
|
+
return null;
|
461
|
+
}
|
462
|
+
|
463
|
+
|
464
|
+
/**
|
465
|
+
* @return {Node|null}
|
466
|
+
*/
|
467
|
+
minNode(t = this._root) {
|
468
|
+
if (t) while (t.left) t = t.left;
|
469
|
+
return t;
|
470
|
+
}
|
471
|
+
|
472
|
+
|
473
|
+
/**
|
474
|
+
* @return {Node|null}
|
475
|
+
*/
|
476
|
+
maxNode(t = this._root) {
|
477
|
+
if (t) while (t.right) t = t.right;
|
478
|
+
return t;
|
479
|
+
}
|
480
|
+
|
481
|
+
|
482
|
+
/**
|
483
|
+
* Returns node at given index
|
484
|
+
* @param {number} index
|
485
|
+
* @return {?Node}
|
486
|
+
*/
|
487
|
+
at (index) {
|
488
|
+
let current = this._root, done = false, i = 0;
|
489
|
+
const Q = [];
|
490
|
+
|
491
|
+
while (!done) {
|
492
|
+
if (current) {
|
493
|
+
Q.push(current);
|
494
|
+
current = current.left;
|
495
|
+
} else {
|
496
|
+
if (Q.length > 0) {
|
497
|
+
current = Q.pop();
|
498
|
+
if (i === index) return current;
|
499
|
+
i++;
|
500
|
+
current = current.right;
|
501
|
+
} else done = true;
|
502
|
+
}
|
503
|
+
}
|
504
|
+
return null;
|
505
|
+
}
|
506
|
+
|
507
|
+
|
508
|
+
/**
|
509
|
+
* @param {Node} d
|
510
|
+
* @return {Node|null}
|
511
|
+
*/
|
512
|
+
next (d) {
|
513
|
+
let root = this._root;
|
514
|
+
let successor = null;
|
515
|
+
|
516
|
+
if (d.right) {
|
517
|
+
successor = d.right;
|
518
|
+
while (successor.left) successor = successor.left;
|
519
|
+
return successor;
|
520
|
+
}
|
521
|
+
|
522
|
+
const comparator = this._comparator;
|
523
|
+
while (root) {
|
524
|
+
const cmp = comparator(d.key, root.key);
|
525
|
+
if (cmp === 0) break;
|
526
|
+
else if (cmp < 0) {
|
527
|
+
successor = root;
|
528
|
+
root = root.left;
|
529
|
+
} else root = root.right;
|
530
|
+
}
|
531
|
+
|
532
|
+
return successor;
|
533
|
+
}
|
534
|
+
|
535
|
+
|
536
|
+
/**
|
537
|
+
* @param {Node} d
|
538
|
+
* @return {Node|null}
|
539
|
+
*/
|
540
|
+
prev (d) {
|
541
|
+
let root = this._root;
|
542
|
+
let predecessor = null;
|
543
|
+
|
544
|
+
if (d.left !== null) {
|
545
|
+
predecessor = d.left;
|
546
|
+
while (predecessor.right) predecessor = predecessor.right;
|
547
|
+
return predecessor;
|
548
|
+
}
|
549
|
+
|
550
|
+
const comparator = this._comparator;
|
551
|
+
while (root) {
|
552
|
+
const cmp = comparator(d.key, root.key);
|
553
|
+
if (cmp === 0) break;
|
554
|
+
else if (cmp < 0) root = root.left;
|
555
|
+
else {
|
556
|
+
predecessor = root;
|
557
|
+
root = root.right;
|
558
|
+
}
|
559
|
+
}
|
560
|
+
return predecessor;
|
561
|
+
}
|
562
|
+
|
563
|
+
|
564
|
+
/**
|
565
|
+
* @return {SplayTree}
|
566
|
+
*/
|
567
|
+
clear() {
|
568
|
+
this._root = null;
|
569
|
+
this._size = 0;
|
570
|
+
return this;
|
571
|
+
}
|
572
|
+
|
573
|
+
|
574
|
+
/**
|
575
|
+
* @return {NodeList}
|
576
|
+
*/
|
577
|
+
toList() {
|
578
|
+
return toList(this._root);
|
579
|
+
}
|
580
|
+
|
581
|
+
|
582
|
+
/**
|
583
|
+
* Bulk-load items. Both array have to be same size
|
584
|
+
* @param {Array<Key>} keys
|
585
|
+
* @param {Array<Value>} [values]
|
586
|
+
* @param {Boolean} [presort=false] Pre-sort keys and values, using
|
587
|
+
* tree's comparator. Sorting is done
|
588
|
+
* in-place
|
589
|
+
* @return {AVLTree}
|
590
|
+
*/
|
591
|
+
load (keys = [], values = [], presort = false) {
|
592
|
+
let size = keys.length;
|
593
|
+
const comparator = this._comparator;
|
594
|
+
|
595
|
+
// sort if needed
|
596
|
+
if (presort) sort(keys, values, 0, size - 1, comparator);
|
597
|
+
|
598
|
+
if (this._root === null) { // empty tree
|
599
|
+
this._root = loadRecursive(this._root, keys, values, 0, size);
|
600
|
+
this._size = size;
|
601
|
+
} else { // that re-builds the whole tree from two in-order traversals
|
602
|
+
const mergedList = mergeLists(this.toList(), createList(keys, values), comparator);
|
603
|
+
size = this._size + size;
|
604
|
+
this._root = sortedListToBST({ head: mergedList }, 0, size);
|
605
|
+
}
|
606
|
+
return this;
|
607
|
+
}
|
608
|
+
|
609
|
+
|
610
|
+
/**
|
611
|
+
* @return {Boolean}
|
612
|
+
*/
|
613
|
+
isEmpty() { return this._root === null; }
|
614
|
+
|
615
|
+
get size () { return this._size; }
|
616
|
+
|
617
|
+
|
618
|
+
/**
|
619
|
+
* @param {NodePrinter=} printNode
|
620
|
+
* @return {String}
|
621
|
+
*/
|
622
|
+
toString (printNode = (n) => n.key) {
|
623
|
+
const out = [];
|
624
|
+
printRow(this._root, '', true, (v) => out.push(v), printNode);
|
625
|
+
return out.join('');
|
626
|
+
}
|
627
|
+
|
628
|
+
|
629
|
+
update (key, newKey, newData) {
|
630
|
+
const comparator = this._comparator;
|
631
|
+
let { left, right } = split(key, this._root, comparator);
|
632
|
+
this._size--;
|
633
|
+
if (comparator(key, newKey) < 0) {
|
634
|
+
right = insert(newKey, newData, right, comparator, this);
|
635
|
+
} else {
|
636
|
+
left = insert(newKey, newData, left, comparator, this);
|
637
|
+
}
|
638
|
+
this._root = merge(left, right, comparator);
|
639
|
+
}
|
640
|
+
|
641
|
+
|
642
|
+
split(key) {
|
643
|
+
return split(key, this._root, this._comparator);
|
644
|
+
}
|
645
|
+
}
|
646
|
+
|
647
|
+
|
648
|
+
function loadRecursive (parent, keys, values, start, end) {
|
649
|
+
const size = end - start;
|
650
|
+
if (size > 0) {
|
651
|
+
const middle = start + Math.floor(size / 2);
|
652
|
+
const key = keys[middle];
|
653
|
+
const data = values[middle];
|
654
|
+
const node = { key, data, parent };
|
655
|
+
node.left = loadRecursive(node, keys, values, start, middle);
|
656
|
+
node.right = loadRecursive(node, keys, values, middle + 1, end);
|
657
|
+
return node;
|
658
|
+
}
|
659
|
+
return null;
|
660
|
+
}
|
661
|
+
|
662
|
+
|
663
|
+
function createList(keys, values) {
|
664
|
+
const head = { next: null };
|
665
|
+
let p = head;
|
666
|
+
for (let i = 0; i < keys.length; i++) {
|
667
|
+
p = p.next = { key: keys[i], data: values[i] };
|
668
|
+
}
|
669
|
+
p.next = null;
|
670
|
+
return head.next;
|
671
|
+
}
|
672
|
+
|
673
|
+
|
674
|
+
function toList (root) {
|
675
|
+
var current = root;
|
676
|
+
var Q = [], done = false;
|
677
|
+
|
678
|
+
const head = { next: null };
|
679
|
+
let p = head;
|
680
|
+
|
681
|
+
while (!done) {
|
682
|
+
if (current) {
|
683
|
+
Q.push(current);
|
684
|
+
current = current.left;
|
685
|
+
} else {
|
686
|
+
if (Q.length > 0) {
|
687
|
+
current = p = p.next = Q.pop();
|
688
|
+
current = current.right;
|
689
|
+
} else done = true;
|
690
|
+
}
|
691
|
+
}
|
692
|
+
p.next = null; // that'll work even if the tree was empty
|
693
|
+
return head.next;
|
694
|
+
}
|
695
|
+
|
696
|
+
|
697
|
+
function sortedListToBST(list, start, end) {
|
698
|
+
const size = end - start;
|
699
|
+
if (size > 0) {
|
700
|
+
const middle = start + Math.floor(size / 2);
|
701
|
+
const left = sortedListToBST(list, start, middle);
|
702
|
+
|
703
|
+
const root = list.head;
|
704
|
+
root.left = left;
|
705
|
+
|
706
|
+
list.head = list.head.next;
|
707
|
+
|
708
|
+
root.right = sortedListToBST(list, middle + 1, end);
|
709
|
+
return root;
|
710
|
+
}
|
711
|
+
return null;
|
712
|
+
}
|
713
|
+
|
714
|
+
|
715
|
+
function mergeLists (l1, l2, compare = (a, b) => a - b) {
|
716
|
+
const head = {}; // dummy
|
717
|
+
let p = head;
|
718
|
+
|
719
|
+
let p1 = l1;
|
720
|
+
let p2 = l2;
|
721
|
+
|
722
|
+
while (p1 !== null && p2 !== null) {
|
723
|
+
if (compare(p1.key, p2.key) < 0) {
|
724
|
+
p.next = p1;
|
725
|
+
p1 = p1.next;
|
726
|
+
} else {
|
727
|
+
p.next = p2;
|
728
|
+
p2 = p2.next;
|
729
|
+
}
|
730
|
+
p = p.next;
|
731
|
+
}
|
732
|
+
|
733
|
+
if (p1 !== null) p.next = p1;
|
734
|
+
else if (p2 !== null) p.next = p2;
|
735
|
+
|
736
|
+
return head.next;
|
737
|
+
}
|
738
|
+
|
739
|
+
|
740
|
+
function sort(keys, values, left, right, compare) {
|
741
|
+
if (left >= right) return;
|
742
|
+
|
743
|
+
const pivot = keys[(left + right) >> 1];
|
744
|
+
let i = left - 1;
|
745
|
+
let j = right + 1;
|
746
|
+
|
747
|
+
while (true) {
|
748
|
+
do i++; while (compare(keys[i], pivot) < 0);
|
749
|
+
do j--; while (compare(keys[j], pivot) > 0);
|
750
|
+
if (i >= j) break;
|
751
|
+
|
752
|
+
let tmp = keys[i];
|
753
|
+
keys[i] = keys[j];
|
754
|
+
keys[j] = tmp;
|
755
|
+
|
756
|
+
tmp = values[i];
|
757
|
+
values[i] = values[j];
|
758
|
+
values[j] = tmp;
|
759
|
+
}
|
760
|
+
|
761
|
+
sort(keys, values, left, j, compare);
|
762
|
+
sort(keys, values, j + 1, right, compare);
|
763
|
+
}
|
764
|
+
|
765
|
+
export default Tree;
|