Last active
December 18, 2015 18:49
-
-
Save cspotcode/5828079 to your computer and use it in GitHub Desktop.
My attempt at the Great Binary Search Experiment: http://reprog.wordpress.com/2010/04/19/are-you-one-of-the-10-percent/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Given an array of numbers, returns either the index containing that number | |
// or `undefined` if the array doesn't contain that number. | |
// Assumes that `list` is a non-sparse JavaScript array, that all items in the list are integers, | |
// and that the list is sorted in ascending order (obviously) | |
// Assumes that `value` is an integer. | |
function binarySearch(list, value) { | |
// Lower bound = minimum possible index | |
var lowerBound = 0; | |
// Upper bound = maximum possible index + 1 | |
var upperBound = list.length; | |
// An index in the middle of our range. We will compute this shortly. | |
var middleIndex; | |
// Loop forever (we will break out of this loop via a return statement) | |
while(true) { | |
// Is our target range of length 0 (or negative!?)? Then the target value must not be in the list | |
if(upperBound - lowerBound <= 0) return undefined; | |
// Compute the index of the middle of our target range | |
// Assumes that upperBound >= lowerBound | |
middleIndex = lowerBound + Math.floor((upperBound - lowerBound) / 2); | |
// Have we found the target value? Great! We're done. | |
if(list[middleIndex] === value) return middleIndex; | |
if(value < list[middleIndex]) { | |
// The middleIndex value is greater than our target value | |
// so the target value comes *before* middleIndex | |
// upperBound = middleIndex, meaning that our range has everything *up to but not including* middleIndex | |
upperBound = middleIndex; | |
} else { | |
// The middleIndex value is less than our target value | |
// so the target value comes *after* middleIndex | |
// lowerBound = middleIndex + 1, meaning that our range has everything *after and not including* middleIndex | |
lowerBound = middleIndex + 1; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Test cases | |
test("empty list", function() { | |
ok(binarySearch([], 4) === undefined); | |
}); | |
test("one-item list", function() { | |
ok(binarySearch([3], 3) === 0); | |
ok(binarySearch([3], 10) === undefined); | |
ok(binarySearch([3], 1) === undefined); | |
}); | |
test("two-item list", function() { | |
var list = [5, 10]; | |
ok(binarySearch(list, 0) === undefined); | |
ok(binarySearch(list, 5) === 0); | |
ok(binarySearch(list, 7) === undefined); | |
ok(binarySearch(list, 10) === 1); | |
ok(binarySearch(list, 12) === undefined); | |
}); | |
test("three-item list", function() { | |
var list = [5, 10, 15]; | |
ok(binarySearch(list, 0) === undefined); | |
ok(binarySearch(list, 5) === 0); | |
ok(binarySearch(list, 7) === undefined); | |
ok(binarySearch(list, 10) === 1); | |
ok(binarySearch(list, 12) === undefined); | |
ok(binarySearch(list, 15) === 2); | |
ok(binarySearch(list, 20) === undefined); | |
}); | |
test("four-item list", function() { | |
var list = [5, 10, 15, 20]; | |
ok(binarySearch(list, 0) === undefined); | |
ok(binarySearch(list, 5) === 0); | |
ok(binarySearch(list, 7) === undefined); | |
ok(binarySearch(list, 10) === 1); | |
ok(binarySearch(list, 12) === undefined); | |
ok(binarySearch(list, 15) === 2); | |
ok(binarySearch(list, 17) === undefined); | |
ok(binarySearch(list, 20) === 3); | |
ok(binarySearch(list, 40) === undefined); | |
}); | |
var totalIterations = 500000; | |
var chunkSize = 1000; | |
for(var i = 0; i < totalIterations / chunkSize; i++) { | |
test("many random lists of random length with random contents, searching for random numbers", function() { | |
var list, length, j, value, listContainsValue, result; | |
for(var i = 0; i < chunkSize; i++) { | |
list = []; | |
length = (Math.random() * 300)|0; | |
for(j = 0; j < length; j++) { | |
list.push((Math.random() * 200)|0); | |
} | |
list.sort(function(a, b) {return a < b ? -1 : a > b ? 1 : 0}); | |
value = (Math.random() * 200)|0; | |
listContainsValue = false; | |
for(j = 0; j < length; j++) { | |
if(list[j] === value) { | |
listContainsValue = true; | |
break; | |
} | |
} | |
result = binarySearch(list, value); | |
ok(result !== undefined || listContainsValue === false, '' + value + ' in ' + JSON.stringify(list)); | |
ok(result === undefined || list[result] === value); | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment