Интерполяционный поиск — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Новая страница: «Пусть <tex>t</tex> - отсортированный массив чисел из <tex>n</tex> чисел. Тогда можно построить отсорт…»)
 
Строка 1: Строка 1:
Пусть <tex>t</tex> - отсортированный массив чисел из <tex>n</tex> чисел. Тогда можно построить отсортированный массив <tex>a: a_i \in[0, 1] \forall i = \bar{1, n}</tex>
+
=== Идея ===
 +
Рассмотрим задачу: найти слово в словаре. Если оно начинается на букву "А", то никто не будет искать его в середине, а откроет словарь ближе к началу. В чем разница между алгоритмом человека и другими? Отличие заключается в том, что алгоритмы вроде двоичного не делают различий между "немного больше" и "существенно больше".
  
Время работы алгоритма: <tex>O(\log \log n)</tex>.
+
=== Алгоритм ===
 +
[[Файл:Search.jpg|thumb|300px|Нахождение медианы]]
 +
Пусть <tex> a </tex> - отсортированный массив чисел из <tex> n </tex> чисел, <tex> x </tex> - значение, которое нужно найти.
 +
Если известно, что <tex> x </tex> лежит между <tex> a_l </tex> и <tex> a_r </tex>, то следующая проверка выполняется примерно на расстоянии <tex dpi = "180"> \frac{x - a_l}{a_r - a_l} </tex>.
 +
 
 +
=== Время работы ===
 +
При условии, что значения элементов близки к арифметической прогрессии, за один шаг алгоритм уменьшает количество проверяемых элементов с <tex> n </tex> до <tex> \sqrt n </tex>.
 +
Поэтому среднее время работы алгоритма: <tex> O(\log \log n) </tex>.
 +
При "плохих" исходных данных (например, при экспоненциальном возрастании элементов) время работы может ухудшиться до <tex> O(n) </tex>.
 +
 
 +
=== Реализация ===
 +
Приведем код функции <tex> interpolation\_search(a, n, x) </tex> на языке C++.
 +
<code>
 +
int interpolation_search(double* a, int n, double x)
 +
{
 +
  int l = 0;
 +
  int r = n - 1;
 +
  int m;
 +
 +
  while (a[l] <= x && x <= a[r])
 +
  {
 +
    mid = l + (x - a[l]) / (a[r] - a[l]) * (r - l);
 +
 +
    if (a[m] == x)
 +
      return m;
 +
    if (a[m] < x)
 +
      l = m + 1;
 +
    else
 +
      r = m - 1;
 +
  }
 +
 +
  if (a[l] == x)
 +
    return l;
 +
  else
 +
    return -1; // not found
 +
}
 +
</code>
 +
 
 +
=== Полезные ссылки ===
 +
Д.Э. Кнут: [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)] <br/>
 +
Wikipedia: [http://en.wikipedia.org/wiki/Interpolation_search Interpolation search]

Версия 04:28, 12 июня 2011

Идея

Рассмотрим задачу: найти слово в словаре. Если оно начинается на букву "А", то никто не будет искать его в середине, а откроет словарь ближе к началу. В чем разница между алгоритмом человека и другими? Отличие заключается в том, что алгоритмы вроде двоичного не делают различий между "немного больше" и "существенно больше".

Алгоритм

Нахождение медианы

Пусть [math] a [/math] - отсортированный массив чисел из [math] n [/math] чисел, [math] x [/math] - значение, которое нужно найти. Если известно, что [math] x [/math] лежит между [math] a_l [/math] и [math] a_r [/math], то следующая проверка выполняется примерно на расстоянии [math] \frac{x - a_l}{a_r - a_l} [/math].

Время работы

При условии, что значения элементов близки к арифметической прогрессии, за один шаг алгоритм уменьшает количество проверяемых элементов с [math] n [/math] до [math] \sqrt n [/math]. Поэтому среднее время работы алгоритма: [math] O(\log \log n) [/math]. При "плохих" исходных данных (например, при экспоненциальном возрастании элементов) время работы может ухудшиться до [math] O(n) [/math].

Реализация

Приведем код функции [math] interpolation\_search(a, n, x) [/math] на языке C++.


int interpolation_search(double* a, int n, double x)
{
  int l = 0;
  int r = n - 1;
  int m;

  while (a[l] <= x && x <= a[r])
  {
    mid = l + (x - a[l]) / (a[r] - a[l]) * (r - l);

    if (a[m] == x)
      return m;
    if (a[m] < x)
      l = m + 1;
    else
      r = m - 1;
  }

  if (a[l] == x)
    return l;
  else
    return -1; // not found
}

Полезные ссылки

Д.Э. Кнут: Искусство программирования (том 3)
Wikipedia: Interpolation search