Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
LektsiiS.doc
Скачиваний:
81
Добавлен:
13.04.2015
Размер:
815.1 Кб
Скачать

3.4 Поиск с порогом

Процедура поиска выполняется столь часто, что ее стараются сделать предельно быстрой. В предыдущем алгоритме на каждом шаге цикла выполнялось три элементарных операции — два сравнения и одно сложение. Сейчас мы увидим алгоритм, в котором тот же результат достигается всего за две операции, т.е. в 1,5 раза быстрее!

В этом алгоритме мы воспользуемся для хранения n чисел массивом из n+1 элемента и в последний элемент поместим искомое число X. Теперь в цикле достаточно проверять лишь совпадение M[count] с X, т.к. число X обязательно присутствует в массиве и будет найдено. По окончании цикла остается лишь уточнить, где именно оно было найдено. Если в последнем элементе массива, то это не “настоящее” X, а искусственное и первоначально его в массиве не было.

Начало

Поместить X в последний элемент массива, M[n] = X;

Установить счетчик элементов в 1, count = 1;

Пока M[count] <> X повторять

увеличить на 1 счетчик чисел: count = count + 1;

Если count = n + 1, то сообщить, что числа X в массиве нет,

иначе вывести count;

Конец

Этот алгоритм носит название поиска с порогом, т.к. мы ставим в массиве тот порог, о который обязательно “споткнется” оператор цикла.

3.5 Двоичный поиск

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

Разделим область поиска (первоначально это весь массив) пополам и сравним искомое число X с числом из середины области. Если число из середины больше, чем X, то дальше искать надо только в первой половине массива, если меньше — во второй, а если равно, то число найдено, и поиск нужно прекратить. Оформим эту идею в виде алгоритма двоичного поиска.

Начало

Установить левую границу области поиска, Left = 1;

Установить правую границу области поиска, Right = n;

Пока левая граница не больше правой, Left <= Right, повторять

Начало

Найти середину области поиска, Middle = (Left + Right) / 2;

Если X < M[Middle], то изменить правую границу, Right=Middle-1;

Если X > M[Middle], то изменить левую границу, Left=Middle+1;

Если X = M[Middle], то вывести значение Middle и закончить работу;

Конец

Сообщить, что числа X в массиве нет

Конец

В процессе выполнения цикла область поиска уменьшается вдвое на каждом шаге цикла, пока не станет пустой или пока число X не будет найдено. Последний оператор выполнится лишь в том случае, если область поиска станет пустой, т.е. числа X в массиве не окажется.

Интересно ответить на вопрос, сколько раз может повториться цикл в данном алгоритме? Иными словами, каково время поиска в худшем случае?

Если в массиве n чисел, то делить область поиска пополам можно не более, чем log n раз (логарифм двоичный от n). Это позволяет оценить временную сложность алгоритма как

,

где Const — константа, не зависящая от n.

Для сравнения заметим, что общая оценка временной сложности всех алгоритмов последовательного поиска

,

т.е. линейная функция от n. По этой причине последовательный поиск часто называют линейным, а двоичный — логарифмическим.

Каким образом упорядочить числа в массиве? На этот вопрос мы ответим в следующем разделе.

Вопросы

1. Как изменить алгоритм поиска наибольшего из введенных чисел, чтобы он находил наименьшее число ?

2. Какова временная сложность поиска наибольшего числа в массиве?

3. Можно ли применить поиск с порогом, если в массиве нет свободных элементов?

4. Предложите алгоритм не двоичного, а троичного поиска.

5. Оцените временную сложность троичного поиска и сравните ее со сложностью двоичного поиска.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]