Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
САОД / САОД1 / Лабораторная работа 1.doc
Скачиваний:
17
Добавлен:
26.04.2015
Размер:
64 Кб
Скачать

2.2. Быстрый последовательный список

Этот метод поиска является небольшим усовершенствованием предыдущего. В любой программе, имеющей циклы, наибольший интерес представляет оптимизация именно циклов, то есть сокращение числа действий в них. Посмотрим на алгоритм линейного поиска (программу раздела 2.1.). В цикле while производится два сравнения: (i<=n) и (A[i]<>Key). Избавимся от одного из них (от первого), положив A[n+1] = Key. Тогда программа поиска будет выглядеть так:

Пример на языке Паскаль:

A[n+1] := Key;

i := 1;

while A[i]<>Key do Inc(i);

ifi<=nthen<элемент найден>else<элемент не найден>;

Пример на языке С:

A[n+1] = Key;

i = 1;

while (A[i]!=Key) i++;

if (i<=n) <элемент найден>;

else <элемент не найден>;

Надо сказать, что хотя такой фрагмент кода будет работать быстрее, но его теоретическая сложность остается такой же – T(n). Гораздо больший интерес представляют методы, не только работающие быстро, но и дающие лучшую теоретическую сложность. Один из таких методов – дихотомический поиск.

2.3. Дихотомический (бинарный) поиск

Этот метод поиска предполагает, что множество хранится, как некоторая отсортированная (например, по возрастанию) последовательность элементов, к которым можно получить прямой доступ посредством индекса. Фактически речь идет о том, что множество хранится в массиве и этот массив отсортирован.

Суть метода заключается в следующем. Областью поиска (l, r) назовем часть массива с индексами от l до r, в которой предположительно находится искомый элемент. Сначала областью поиска будет часть массива (l, r), где l=0, а r=n-1, то есть вся заполненная элементами множества часть массива. Теперь найдем индекс среднего элемента m=(l+r) div2. Если Key>A[m], то можно утверждать (поскольку массив отсортирован), что если Key есть в массиве, то он находится в одном из элементов с индексами от m+l до r, следовательно, можно присвоить l=m+1, сократив область поиска. В противном случае можно положить r=m. На этом заканчивается первый шаг метода. Остальные шаги аналогичны.

На каждом шаге метода область поиска будет сокращаться вдвое. Как только l станет равно r, то есть область поиска сократится до одного элемента, можно будет проверить этот элемент на равенство искомому и сделать вывод о результате поиска.

Запишем все сказанное в виде программы:

Пример на языке Паскаль:

l:= 1;r:=n;

while (l<>r) do

begin

m := (l+r) div 2;

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)/2;

if (Key>A[m]) l=m+1;

else r=m;

}

if (A[l]==Key) <Элемент найден>;

else <Элемент не найден>;

Как уже было сказано, область поиска на каждом шаге сокращается вдвое, а это означает сложность T(log(n)).

Особого внимания здесь заслуживают операции добавления и удаления. Они должны сохранять массив отсортированным (лучше написать операции так, чтобы они не нарушали отсортированности массива, чем каждый раз сортировать его). Рассмотрим сначала добавление.

Чтобы при добавлении массив остался отсортированным, новый элемент должен быть вставлен в массив так, чтобы ему предшествовали меньшие элементы, а за ним следовали большие. То есть элементы, стоящие в месте вставки и за ним до конца массива должны быть сдвинуты на одну позицию в сторону конца массива:

Пример на языке Паскаль:

i:=n;

while (i>=1)and(A[i]>Key) do

begin

A[i+1] := A[i]; {сдвигаем}

Dec(i);

end;

A[i+1] := Key;

Inc(n);

Пример на языке С:

i = n;

while ((i>=1) && (A[i]>Key))

{

A[i+1]=A[i]; //сдвигаем

i--;

}

A[i+1] = Key;

n++;

Такая операция добавления имеет сложность T(n).

Удаление в том виде, в каком оно записано в разделе 2.1. сохраняет массив отсортированным.