node-sort
Version:
A sorting library for Node.js
303 lines (271 loc) • 7.61 kB
JavaScript
;
/*!
* 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;