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

3 Линейный поиск

Поиск – одна из наиболее часто встречающихся в программировании задач, кроме того она очень удобна, чтобы испытывать различные структуры данных. Для определенности примем, что поиск будет осуществляться в массиве

Var a:array [0..n-1] of item

Обычно тип item описывает запись с некоторым полем выполняющим роль ключа. Задача заключается в том, что необходимо найти элемент ключ которого = заданному аргументу поиска Х, т. к. нас интересует сам процесс поиска, то для простоты будем считать, что тип item включает только ключ. Если нет никакой информации о разыскиваемых данных, то очевидный подход – простой последовательный просмотр массива с увеличением шаг за шагом той его части где желаемый еле-т не обнаружен. Условия окончания поиска – 1) эле-т найден ai=x 2) если все просмотрено а совпадений нет.

I:=0; While (I<n) and (a[I]<>x do I:=I+1;

Замечание: порядок эл-тов в лог. Выражении имеет существенное значение.

Инвариант цикла – т. е. условие выполняется перед каждым увеличением индекса. Записывается

(0<= I <N)&(для любого K: 0<=k< I: ak не =x)

Отсюда можно вывести условие окончания

((I=n) or (ai=x))& (для любого K: 0<=k< I: ak не =x)

Это условие указывает на желаемый результат, а также указывает, что если желаемый эл-т найден, то он найден с мин. индексом. Равенство I=N означает, что совпадений не было. На каждом шаге требуется вычисление индекса и лог. выражение. Единственная возможность ускорить поиск - попытаться упростить лог. выражение, т. к. оно состоит из 2-х членов, т. е. надо сформулировать простое условие эквивалентное исходному. Это можно зделать если мы гарантируем, что совпадение всегда произойдет. Для этого достаточно поместить в конец массива дополнительный эле-т со значение Х – барьер. Он будет охранять от перехода за границы барьера.

Var a:array [0..n] of item

Алгоритм

A[n]:=x; I:=0;

While a[I]<>x do I:=I+1;

4 Поиск делением пополам (двоичный поиск)

Поиск – одна из наиболее часто встречающихся в программировании задач, кроме того она очень удобна, чтобы испытывать различные структуры данных.

Для определенности примем, что поиск будет осуществляться в массиве

Var a:array [0..n-1] of item

Обычно тип item описывает запись с некоторым полем выполняющим роль ключа. Задача заключается в том, что необходимо найти элемент ключ которого = заданному аргументу поиска Х, т. к. нас интересует сам процесс поиска, то для простоты будем считать, что тип item включает только ключ.

Известно, что поиск можно сделать более эффективным если данные будут упорядочены, т. е. они будут подчинятся условию

Для любого k: 1<=k<n

Основная идея выбратьслучайный некоторый эле-т и сравнить его с аргументом поиска Х – если он =Х то поиск заканчивается, если он <Х то заключаем, что эл-ты с индексами меньшими или = m можно исключить из дальнейшего поиска, если>х то исключаются эл-ты с индексами =>m.

L:=0; R:=N-1; found:=false; {L и Rотмечают левый и правый конец секции массива где можно обнаружить искомый эле-т}

While (l<=R) and (not found) do

Begin M:=(любое значение между L и R); If a[m]=x then found:=trye Else if a[m]<x then L:=m+1 Else R:=m-1; End;

Инвариант

(L<=R)&(для любого k: 0<=k<L:ak<x)&(для любого k: R<k<n:ak>x)

Выбор совершенно произволен в том смысле, что корректность не зависит от него, однако этот выбор влияет на эффективность. Самый оптимальный вариант – средний элемент, т. к. на каждом шаге исключается половина массива. В результате мак. число сравнений порядка log n. Приведенный алгоритм выигрывает по сравнению с линейным где ожидаемое число сравнений n/2.

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

Быстрый алгоритм построен на инварианте

(для любого K: 0<=k< α: ak<x)& (для любого K: r<=k<n : ak =>x)

Поиск продолжается пока обе секции не накроят массив целиком.

L:=0; R:=N;

While L<R do Begin M:=(L+R) div 2 If a[m]<x then L:=m+1 Else R:=m; Условие окончания L=>R

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