Интерполяционный поиск — различия между версиями
Gromak (обсуждение | вклад) (Пока так) |
Gromak (обсуждение | вклад) |
||
| Строка 4: | Строка 4: | ||
== Алгоритм == | == Алгоритм == | ||
[[Файл:Search.jpg|thumb|300px|Нахождение разделительного элемента]] | [[Файл:Search.jpg|thumb|300px|Нахождение разделительного элемента]] | ||
| − | Пусть <tex> a </tex> {{---}} отсортированный массив чисел из <tex> n </tex> чисел, <tex> x </tex> {{---}} значение, которое нужно найти. | + | Пусть <tex> a </tex> {{---}} отсортированный массив чисел из <tex> n </tex> чисел, <tex> x </tex> {{---}} значение, которое нужно найти. Поиск происходит подобно [[Целочисленный двоичный поиск|двоичному поиску]], но вместо деления области поиска на две примерно равные части, интерполирующий поиск производит оценку новой области поиска по расстоянию между ключом и текущим значением элемента. Если известно, что <tex> x </tex> лежит между <tex> a_l </tex> и <tex> a_r </tex>, то следующая проверка выполняется примерно на расстоянии <tex dpi = "170"> \frac{x - a_l}{a_r - a_l} </tex> от <tex> l </tex>. |
=== Псевдокод === | === Псевдокод === | ||
<code> | <code> | ||
| − | + | interpolationSearch(n, x): | |
| − | + | l = 0; // левая граница поиска (будем считать, что элементы массива нумеруются с нуля) | |
| − | + | r = n - 1; // правая граница поиска | |
| − | |||
| − | |||
| − | while | + | while a[l] <= x && x <= a[r] |
| − | + | m = l + (x - a[l]) / (a[r] - a[l]) * (r - l); // элемент, с которым будем проводить сравнение | |
| − | m = l + (x - a[l]) / (a[r] - a[l]) * (r - l); | + | if a[m] == x |
| − | + | result = m; | |
| − | if | + | if a[m] < x |
| − | |||
| − | if | ||
l = m + 1; | l = m + 1; | ||
else | else | ||
r = m - 1; | r = m - 1; | ||
| − | |||
| − | if | + | if a[l] == x |
| − | + | result = l; | |
else | else | ||
| − | + | result = -1; // not found | |
| − | |||
</code> | </code> | ||
| Строка 38: | Строка 32: | ||
При "плохих" исходных данных (например, при экспоненциальном возрастании элементов) время работы может ухудшиться до <tex> O(n) </tex>. | При "плохих" исходных данных (например, при экспоненциальном возрастании элементов) время работы может ухудшиться до <tex> O(n) </tex>. | ||
| + | |||
| + | Эксперименты показали, что интерполяционный поиск не настолько снижает количество выполняемых сравнений, чтобы компенсировать требуемое для дополнительных вычислений время (пока таблица не очень велика). Кроме того, типичные таблицы недостаточно случайны, да и разница между значениями <tex>\log \log n</tex> и <tex>\log n</tex> становится значительной только при очень больших <tex>N</tex>. На практике при поиске в больших файлах оказывается выгодным на ранних стадиях применять интерполяционный поиск, а затем, когда диапазон существенно уменьшится, переходить к двоичному. | ||
== Литература == | == Литература == | ||
| − | Д.Э. Кнут: [http://books.google.com/books?id=92rW-nktlbgC&pg=PA452&lpg=PA453&ots=jChsP2sutg&dq=%D0%BA%D0%BD%D1%83%D1%82+%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D0%BE%D0%BB%D1%8F%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9+%D0%BF%D0%BE%D0%B8%D1%81%D0%BA&hl=ru&ie=windows-1251&output=html Искусство программирования (том 3)] | + | Д.Э. Кнут: [http://books.google.com/books?id=92rW-nktlbgC&pg=PA452&lpg=PA453&ots=jChsP2sutg&dq=%D0%BA%D0%BD%D1%83%D1%82+%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D0%BE%D0%BB%D1%8F%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9+%D0%BF%D0%BE%D0%B8%D1%81%D0%BA&hl=ru&ie=windows-1251&output=html Искусство программирования (том 3)] |
| + | |||
Wikipedia: [http://en.wikipedia.org/wiki/Interpolation_search Interpolation search] | Wikipedia: [http://en.wikipedia.org/wiki/Interpolation_search Interpolation search] | ||
| + | |||
| + | Wikipedia: [http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D0%BE%D0%BB%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA Интерполирующий поиск] | ||
[[Категория: Дискретная математика и алгоритмы]] | [[Категория: Дискретная математика и алгоритмы]] | ||
[[Категория: Алгоритмы поиска]] | [[Категория: Алгоритмы поиска]] | ||
Версия 12:25, 17 мая 2012
Содержание
Идея
Рассмотрим задачу: найти слово в словаре. Если оно начинается на букву "А", то никто не будет искать его в середине, а откроет словарь ближе к началу. В чём разница между алгоритмом человека и другими? Отличие заключается в том, что алгоритмы вроде двоичного поиска не делают различий между "немного больше" и "существенно больше".
Алгоритм
Пусть — отсортированный массив чисел из чисел, — значение, которое нужно найти. Поиск происходит подобно двоичному поиску, но вместо деления области поиска на две примерно равные части, интерполирующий поиск производит оценку новой области поиска по расстоянию между ключом и текущим значением элемента. Если известно, что лежит между и , то следующая проверка выполняется примерно на расстоянии от .
Псевдокод
interpolationSearch(n, x):
l = 0; // левая граница поиска (будем считать, что элементы массива нумеруются с нуля)
r = n - 1; // правая граница поиска
while a[l] <= x && x <= a[r]
m = l + (x - a[l]) / (a[r] - a[l]) * (r - l); // элемент, с которым будем проводить сравнение
if a[m] == x
result = m;
if a[m] < x
l = m + 1;
else
r = m - 1;
if a[l] == x
result = l;
else
result = -1; // not found
Время работы
Асимптотически интерполяционный поиск превосходит по своим характеристикам бинарный. Если ключи распределены случайным образом, то за один шаг алгоритм уменьшает количество проверяемых элементов с до . То есть, после -ого шага количество проверяемых элементов уменьшается до . Значит, остаётся проверить только 2 элемента (и закончить на этом поиск), когда . Из этого вытекает, что количество шагов, а значит, и время работы составляет .
При "плохих" исходных данных (например, при экспоненциальном возрастании элементов) время работы может ухудшиться до .
Эксперименты показали, что интерполяционный поиск не настолько снижает количество выполняемых сравнений, чтобы компенсировать требуемое для дополнительных вычислений время (пока таблица не очень велика). Кроме того, типичные таблицы недостаточно случайны, да и разница между значениями и становится значительной только при очень больших . На практике при поиске в больших файлах оказывается выгодным на ранних стадиях применять интерполяционный поиск, а затем, когда диапазон существенно уменьшится, переходить к двоичному.
Литература
Д.Э. Кнут: Искусство программирования (том 3)
Wikipedia: Interpolation search
Wikipedia: Интерполирующий поиск