2.4. Интерполяционный поиск
Рассмотрим еще один метод, имеющий хорошую теоретическую сложность. Как и предыдущий, этот метод предполагает, что множество хранится в массиве и массив отсортирован. Как и предыдущий метод, этот на каждом шаге своей работы сокращает область поиска. Но в отличие от предыдущего метода проба берется не в середине рассматриваемой области.
Пусть имеется область поиска (l, r). Предположим, что элементы множества – целые числа, возрастающие в арифметической прогрессии. Тогда искомый элемент должен находится в массиве (если он вообще там есть) под индексом (Это следует из свойств арифметической прогрессии)
В этом элементе и будем брать пробу.
Пример на языке Паскаль:
l:= 1;r:=n;
while (l<>r) do
begin
m := l+(r-l)*(Key-A[l])/(A[r]-A[l]);
if Key>A[m] then l := m+1 else r := m;
end;
ifA[l]=Keythen<элемент найден>else<элемент не найден>;
Пример на языке С:
l=1;
r=n;
while (l!=r)
{
m=l+(r-l)*(Key-A[l])/(A[r]-A[l]);
if (Key>A[m]) l= m+1;
else r= m;
}
if (A[l]==Key) <элемент найден>;
else <элемент не найден>;
Мы сделали очень большое допущение, предположив, что элементы массива представляют собой возрастающую арифметическую прогрессию. В реальности такая ситуация встречается редко. Но этот метод хорошо работает для любых пусть не идеально, но более-менее равномерно распределенных данных. Если же мы имеем дело с неравномерно распределенными данными, то интерполяционный поиск может увеличить число шагов по сравнению с дихотомическим поиском. Теоретическая сложность интерполяционного поиска – T(log(log(n))). Это, конечно, лучше, чем сложность дихотомического поиска, но эти преимущества становятся достаточно заметными лишь при очень больших значениях n. Практически на всех реальных n разница между дихотомическим и интерполяционным поиском по скорости не существенна.
3. Методические указания
В этой и последующих лабораторных работах вам понадобиться узнать время выполнения программы, для решения этой задачи в языке С/С++ есть функция clock() описанная в заголовочном файле <time.h>.
Описание функции следующее:
clock_tclock(void);
Здесь clock_t – тип данных, определенный в файле time.h. Функция возвращает процессорное время в единицах, которые зависят от реализации языка. (Если процессорное время недоступно или не может быть представлено, функция возвращает значение -1.) Однако в файле time.h также определена константа СLOCKS_PER_SEC, которая представляет количество единиц процессорного времени в секунде. Следовательно, в результате деления разницы между двумя возвращаемыми значениями функции clock () на константу CLOCKS_PER_SEC получается количество секунд, прошедшее между двумя вызовами функции. Приведение значений к типу double до операции деления позволит получать результат в долях секунды. Например если вам необходимо получить время выполнения каких-либо действий то вам необходимо вставить в программу следующий код:
#include <time.h>
......
clock_t time;
time = clock();
/* какие-то действия */
time = clock() - time;
printf("%f", (double)time/CLOCKS_PER_SEC); //время выполнения "каких-то действий"