While re-writing some old JavaScript code to better handle large arrays, I ended up writing my own binary search method.
I found many examples of binary search methods written in JavaScript, but all the examples I found returned -1 whenever the target was not found in the array. What I really wanted was the bitwise complement of the index where the target belonged if it did not exist in the array, like the BinarySearch method on generic lists in .NET.
This is the code I ended up writing, but I'm curious if I've overlooked any potential performance problems or logic errors. To the best of my knowledge, the code works sufficiently as designed (see my fiddle). Please help me review this code and verify that it follows common best practices.
binarySearch Method
Inputs: target
: the object being sought in the array; comparator
: (optional) comparison method
Returns: If positive or zero, the index of the item in the array. If negative, the bitwise complement of the item's proper location in the array.
Array.prototype.binarySearch = function (target, comparator) { var l = 0, h = this.length - 1, m, comparison; while (l <= h) { m = (l + h) >> 1; comparison = typeof (comparator) == "undefined" ? (this[m] < target ? -1 : (this[m] > target ? 1 : 0)) : comparator(this[m], target); if (comparison < 0) { l = m + 1; continue; } else if (comparison > 0) { h = m - 1; continue; } else { return m; } } return~l; };
Using the above, I also wrote a binary insert method, which adds an item to the correct location in an array. I'm curious about this also, and whether there's anything I can do to improve its performance or handle any edge case bugs.
binaryInsert Method
Inputs:target
: object being inserted; duplicate
: (optional) whether to add if it already exists in the array (false by default); comparator
: (optional) comparison method
Returns: Index of new item added to array
Array.prototype.binaryInsert = function (target, duplicate, comparator) { if (typeof (duplicate) == "undefined") duplicate = false; var i = this.binarySearch(target, comparator); if (i >= 0) { if (duplicate) { this.splice(i, 0, target); } } else { i = ~i; this.splice(i, 0, target); } return i; };