ekylibre-cartography 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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;
|