UNPKG

node-sort

Version:

A sorting library for Node.js

303 lines (271 loc) 7.61 kB
"use strict"; /*! * Sorting Algorithm Node.js Library * Author: Kevin Coughlin @kevintcoughlin <kevintcoughlin@gmail.com> * MIT Licensed */ /** * Sorting Algorithm Client */ function Sort() { if (!(this instanceof Sort)) { return new Sort(); } /** * Default Comparison Function * * @param {Object} left Object from left array * @param {Object} right Object from right array */ this.defaultComparator = function(left, right) { if (left > right) return 1 else if (left < right) return -1 else if (left == right) return 0 } } /** * Merge Sort * Complexity: O(n*log(n)) * * @param {Array} array Array to be merge sorted. * @param {Function} comparator Comparison function. */ Sort.prototype.mergeSort = function(array, comparator) { // If array is null, no data to sort. Throw error. if (array == null) { throw new Error('ERROR: Array cannot be null.'); } // If array is not of type Array. Throw error. else if (!Array.isArray(array)) { throw new Error('ERROR: Array passed is not of type "Array"'); } // If comparator was passed but not a function use default if (typeof comparator != "function") { comparator = this.defaultComparator; } var length = array.length , mid = Math.ceil(length / 2) , left = array.slice(0, mid) , right = array.slice(mid, length); // Array is sorted, return if (length <= 1) { return array; } /** * Merges two arrays. Shifts either left or right object * onto result array depending which is lower value || exists. * * @param {Array} left The left sub-array * @param {Array} right The right sub-array */ function merge(left, right) { var result = []; // While either array exists while(left.length || right.length) { // If both exist if(left.length && right.length) { // Left value less than right value, shift left onto result if(comparator(left[0], right[0]) < 0) { result.push(left.shift()); } // Shift right onto result else { result.push(right.shift()); } } // If only left exists, shift left onto result else if (left.length) { result.push(left.shift()); } // If only right exists, shift right onto result else { result.push(right.shift()); } } // Return merged array return result; } // Merge recursively sorted sub arrays return merge(this.mergeSort(left, comparator), this.mergeSort(right, comparator)); } /** * Bubble Sort * Complexity: O(n^2) * * @param {Array} array Array to sort. * @param {Function} comparator Comparator function. */ Sort.prototype.bubbleSort = function(array, comparator) { // If array is null, no data to sort. Throw error. if (array == null) { throw new Error('ERROR: Array cannot be null.'); } // If array is not of type Array. Throw error. else if (!Array.isArray(array)) { throw new Error('ERROR: Array passed is not of type "Array"'); } // If comparator was passed but not a function use default if (typeof comparator != "function") { comparator = this.defaultComparator; } // Array is sorted, return if (array.length <= 1) { return array; } for (var i = 0; i < array.length; i++) { for (var k = array.length - 1; k > i; k--) { if (comparator(array[k], array[k-1]) < 0) { var temp = array[k]; array[k] = array[k - 1]; array[k - 1] = temp; } } } return array; } /** * Selection Sort * Complexity: O(n^2) * * @param {Array} array Array to sort. * @param {Function} comparator Comparator function. */ Sort.prototype.selectionSort = function(array, comparator) { // If array is null, no data to sort. Throw error. if (array == null) { throw new Error('ERROR: Array cannot be null.'); } // If array is not of type Array. Throw error. else if (!Array.isArray(array)) { throw new Error('ERROR: Array passed is not of type "Array"'); } // If comparator was passed but not a function use default if (typeof comparator != "function") { comparator = this.defaultComparator; } // Array is sorted, return if (array.length <= 1) { return array; } for (var i = 0; i < array.length; i++) { var selectedIndex = i; for(var k = i; k < array.length; k++) { if (comparator(array[k], array[selectedIndex]) < 0) { selectedIndex = k; } } var key = array[i]; array[i] = array[selectedIndex]; array[selectedIndex] = key; } return array; } /** * Insertion Sort * Complexity: O(n^2) * * @param {Array} array Array to sort. * @param {Function} comparator Comparator function. */ Sort.prototype.insertionSort = function(array, comparator) { // If array is null, no data to sort. Throw error. if (array == null) { throw new Error('ERROR: Array cannot be null.'); } // If array is not of type Array. Throw error. else if (!Array.isArray(array)) { throw new Error('ERROR: Array passed is not of type "Array"'); } // If comparator was passed but not a function use default if (typeof comparator != "function") { comparator = this.defaultComparator; } // Array is sorted, return if (array.length <= 1) { return array; } for (var i = 1; i < array.length; i++) { var key = array[i]; var k = i - 1; while (k >= 0 && (comparator(array[k], key) > 0)) { array[k + 1] = array[k]; k = k - 1; } array[k + 1] = key; } return array; } /** * Bucket Sort * Avg. Case: O(n+k) * * @param {Array} array Array to sort. * @param {Function} comparator Comparator function. * * TODO: Number of buckets param? Sort.prototype.bucketSort = function(array, comparator) { // If array is null, no data to sort. Throw error. if (array == null) { throw new Error('ERROR: Array cannot be null.'); } // If array is not of type Array. Throw error. else if (!Array.isArray(array)) { throw new Error('ERROR: Array passed is not of type "Array"'); } // Array is sorted, return if (array.length <= 1) { return array; } } */ /** * Quick Sort * Complexity: O(n*log(n)) * * @param {Array} array Array to sort. * @param {Function} comparator Comparator function. Sort.prototype.quickSort = function(array, p, r, comparator) { // If array is null, no data to sort. Throw error. // If array is null, no data to sort. Throw error. if (array == null) { throw new Error('ERROR: Array cannot be null.'); } // If array is not of type Array. Throw error. else if (!Array.isArray(array)) { throw new Error('ERROR: Array passed is not of type "Array"'); } // Array is sorted, return if (array.length <= 1) { return array; } } */ /** * Linearly checks if array is sorted * * Avg. Complexity: O(n) * * @param {Array} array Array to check * @param {Function} comparator Comparator function. */ Sort.prototype.isSorted = function(array, comparator) { // If array is null, no data to check. Throw error. if (array == null) { throw new Error('ERROR: Array cannot be null.'); } // If array is not of type Array. Throw error. else if (!Array.isArray(array)) { throw new Error('ERROR: Array passed is not of type "Array"'); } // If comparator was passed but not a function use default if (typeof comparator != "function") { comparator = this.defaultComparator; } for(var i = 1; i < array.length; i++) { if (comparator(array[i - 1], array[i]) > 0) { return false; } } return true; } module.exports = Sort;