Участник:Shovkoplyas Grigory — различия между версиями
| Строка 8: | Строка 8: | ||
=== Псевдокод === | === Псевдокод === | ||
<code style = "display: inline-block;"> | <code style = "display: inline-block;"> | ||
| − | function interpolation_search(a : int[], key : int) //a должен быть отсортирован | + | '''function''' interpolation_search(a : '''int[]''', key : '''int''') <font color=green> //a должен быть отсортирован </font> |
| − | left = 0 // левая граница поиска (будем считать, что элементы массива нумеруются с нуля) | + | left = 0 <font color=green> // левая граница поиска (будем считать, что элементы массива нумеруются с нуля) </font> |
| − | right = a.length - 1 // правая граница поиска | + | right = a.length - 1 <font color=green> // правая граница поиска </font> |
| − | while a[left] <tex> \le </tex> key and key <tex> \le </tex> a[right] | + | '''while''' a[left] <tex> \le </tex> key '''and''' key <tex> \le </tex> a[right] |
| − | mid = left + (key - a[left]) / (a[right] - a[left]) * (right - left) // индекс элемента, с которым будем проводить сравнение | + | mid = left + (key - a[left]) / (a[right] - a[left]) * (right - left) <font color=green> // индекс элемента, с которым будем проводить сравнение </font> |
| − | if a[mid] == key | + | '''if''' a[mid] == key |
| − | return mid | + | '''return''' mid |
| − | if a[mid] < key | + | '''if''' a[mid] < key |
left = mid + 1 | left = mid + 1 | ||
| − | else | + | '''else''' |
right = mid - 1 | right = mid - 1 | ||
| − | if a[left] == key | + | '''if''' a[left] == key |
| − | return left | + | '''return''' left |
| − | else | + | '''else''' |
| − | return -1 // если такого элемента в массиве нет | + | '''return''' -1 <font color=green>// если такого элемента в массиве нет </font> |
</code> | </code> | ||
Версия 14:10, 15 июня 2014
Содержание
Идея
Рассмотрим задачу: найти слово в словаре. Если оно начинается на букву "А", то никто не будет искать его в середине, а откроет словарь ближе к началу. В чём разница между алгоритмом человека и другими? Отличие заключается в том, что алгоритмы вроде двоичного поиска не делают различий между "немного больше" и "существенно больше".
Алгоритм
Пусть — отсортированный массив чисел из чисел, — значение, которое нужно найти. Поиск происходит подобно двоичному поиску, но вместо деления области поиска на две примерно равные части, интерполирующий поиск производит оценку новой области поиска по расстоянию между ключом и текущим значением элемента. Если известно, что лежит между и , то следующая проверка выполняется примерно на расстоянии от .
Псевдокод
function interpolation_search(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: Интерполирующий поиск
