Created
November 26, 2015 10:31
-
-
Save drzhbe/9fea20e53809938ae214 to your computer and use it in GitHub Desktop.
Binary search for closest value
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
/*! | |
Бинарный поиск ближайшего значения. Если значение за пределами списка, возвращает индекс крайнего элемента. | |
Возвращает индекс найденного элемента. | |
x >> 1 === Math.floor(x / 2) | |
\param type:array list | |
\param type:number value | |
\param type:function getVal функция, которая достает нужное значение из элемента списка list | |
\returns type:number | |
*/ | |
function binaryClosestSearch(list, value, getVal) { | |
if (!getVal) { | |
getVal = function(val) { return val; }; | |
} | |
var start = 0; | |
var end = list.length - 1; | |
var mid = (end + start) >> 1; | |
while (start < end && getVal(list[mid]) !== value) { | |
if (value < getVal(list[mid])) { | |
end = mid - 1; | |
} else if (value > getVal(list[mid])) { | |
start = mid + 1; | |
} | |
mid = (end + start) >> 1; | |
} | |
var result; | |
if (getVal(list[mid]) === value) { | |
result = mid; | |
} else { | |
// Точного совпадения не было, ищем ближайший к искомому элемент. | |
var prev = mid - 1; | |
var next = mid + 1; | |
function diff(index) { | |
return Math.abs(value - getVal(list[index])); | |
} | |
// Проверяем значения вокруг mid, если они есть, то будем сравнить разницу value с ними. | |
// Если какого-то из них нет, то вместо него берем сам mid. | |
if (prev < 0) { | |
result = diff(mid) < diff(next) ? mid : next; | |
} else if (next >= list.length) { | |
result = diff(prev) < diff(mid) ? prev : mid; | |
} else { | |
// Если есть оба значения вокруг, то сравниваем разницу всех трех значений с value. | |
if (diff(prev) < diff(mid)) { | |
result = diff(prev) < diff(next) ? prev : next; | |
} else { | |
result = diff(mid) < diff(next) ? mid : next; | |
} | |
} | |
} | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment