UNPKG

ibowankenobi-mergesort

Version:

Merge Sort algorithm implementation without recursion, using cached binary trees

92 lines (86 loc) 3.34 kB
import temp from './temp.js'; import walk from './walk.js'; import tree from './tree.js'; import regen from './regen.js'; /** * An optinal configuration object that can be passed to the `Mergesort` factory function * @typedef {Object} module:Mergesort~config * @property {number} threshold The threshold below where the algorithm temporarily switches over to insertion sort * @property {number} size Use this if you are going to consistently sort arrays of fixed size. * Refers to size of the array to be sorted, where a binary tree is precalculated. * The tree will be reused for each call of the returned `instance`. * For each use, the tree is *walked* by setting `firstChild` properties of leaf nodes to null * and then regenerated by setting them again from the `lastChild` property of their parent. * This option results in a performance gain for large (> 1M) arrays, where cost of creating * the tree is greater than the cost of walking + regenerating the tree. For small arrays, * it has the reverse effect. It is set to off by default. */ const undef = void(0); /** * Returns a `Mergesort` `instance` * * ```javascript * * let instance = Mergesort(); //switches to insertion sort for array fragments < 16 * * instance = Mergesort({threshold: 64}); //will switch to insertion sort for fragments < 64 * * instance = Mergesort({size:999}); //will throw an error if you try to sort arrays with length other than 999 * * ``` * * @alias module:Mergesort * * @param {module:Mergesort~config} config a configuration object with optional parameters (default 16) * @returns {module:Mergesort~instance} * */ export default function( { threshold = 16, size = undef } = { threshold: 16, size: undef } ){ if(size && typeof size !== "number"){ throw new Error("Size must be of type number"); } const hThreshold = threshold / 2, _tree = size ? tree(size) : undef, /** * * ```javascript * let instance = Mergesort(), * * inputArray = [{value:10},{value:1},{value:5}], * * compare = (a, b) => a.value - b.value; * * instance(inputArray, compare); //[{value:1}, ...] * * @namespace * @param {Array} ArrayToBeSorted - Input array to be sorted * @param {Function} Compare - compare function, same as in [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) * @returns {Array} input array */ instance = function(arr, f){ let _length = arr.length; if(_tree){ if (_length !== _tree.l) { throw new Error("Array length must be " + size); } temp.length = _length; walk(arr, _tree, f, hThreshold ,true); regen(_tree); } else { temp.length = _length; walk(arr, tree(_length), f, hThreshold); } temp.length = 0; return arr; }; return instance; }