Участник:Shovkoplyas Grigory
Идея
Рассмотрим задачу: найти слово в словаре. Если оно начинается на букву "А", то никто не будет искать его в середине, а откроет словарь ближе к началу. В чём разница между алгоритмом человека и другими? Отличие заключается в том, что алгоритмы вроде двоичного поиска не делают различий между "немного больше" и "существенно больше".
Алгоритм
Пусть двоичному поиску, но вместо деления области поиска на две примерно равные части, интерполирующий поиск производит оценку новой области поиска по расстоянию между ключом и текущим значением элемента. Если известно, что лежит между и , то следующая проверка выполняется примерно на расстоянии от .
— отсортированный массив из чисел, — значение, которое нужно найти. Поиск происходит подобноФормула для разделительного элемента
получается из следующего уравнения: — откуда следует, что . На рисунке внизу показано, из каких соображений берется такая оценка. Интерполяционный поиск основывается на том, что наш массив представляет из себя что-то наподобии арифметической прогрессии.Псевдокод
function interpolationSearch(a : int[], key : int) // a должен быть отсортирован left = 0 // левая граница поиска (будем считать, что элементы массива нумеруются с нуля) right = a.length - 1 // правая граница поиска while a[left]key and key a[right] mid = left + (key - a[left]) / (a[right] - a[left]) * (right - left) // индекс элемента, с которым будем проводить сравнение if a[mid] == key return mid if a[mid] < key left = mid + 1 else right = mid - 1 if a[left] == key return left else return -1 // если такого элемента в массиве нет
Время работы
Асимптотически интерполяционный поиск превосходит по своим характеристикам бинарный. Если ключи распределены случайным образом, то за один шаг алгоритм уменьшает количество проверяемых элементов с
до . То есть, после -ого шага количество проверяемых элементов уменьшается до . Значит, остаётся проверить только 2 элемента (и закончить на этом поиск), когда . Из этого вытекает, что количество шагов, а значит, и время работы составляет .При "плохих" исходных данных (например, при экспоненциальном возрастании элементов) время работы может ухудшиться до
.Эксперименты показали, что интерполяционный поиск не настолько снижает количество выполняемых сравнений, чтобы компенсировать требуемое для дополнительных вычислений время (пока таблица не очень велика). Кроме того, типичные таблицы недостаточно случайны, да и разница между значениями
и становится значительной только при очень больших . На практике при поиске в больших файлах оказывается выгодным на ранних стадиях применять интерполяционный поиск, а затем, когда диапазон существенно уменьшится, переходить к двоичному.Литература
Д.Э. Кнут: Искусство программирования (том 3)
Wikipedia: Interpolation search
Wikipedia: Интерполирующий поиск