Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
find8_1.doc
Скачиваний:
37
Добавлен:
12.03.2015
Размер:
3.46 Mб
Скачать

4.1. Задача поиска на множестве

В дальнейшем, задачу поиска будем описывать тройками . Если элементы множестварасположены в памяти компьютера в некотором адресном пространстве, то наиболее напрашивающимся подходом к поиску представляется подбор функции, позволяющей преобразовывать пространство ключей в адресное пространство. Однако в общем случае нахождение хорошей функциипредставляет непростую задачу, и подобные задачи имеют решение в частных случаях, когда число ключей относительно невелико. Такой подход, названный поиском с использованием индексации по ключам, рассмотрен в [3]. В случае, когда множество значений ключей заранее неизвестно или велико, приходится использовать другие модели поиска, и устанавливать связи между значением ключа и адресом другими методами. Рассмотрим различные подходы к решению задачи поиска в зависимости от имеющейся информации о множестве:

Последовательный поиск:Предположим, что нет никакой информации, о структуре множества. Любая процедура поиска предполагает сравнение элементас элементами множества. Результатом сравнения может быть совпадение элементов, которое означает, что поиск завершен удачно, или отрицательный ответ, который предполагает, что процедура поиска должна быть продолжена. Конечно, значение предикатадает определенную информацию о свойствах элемента. Поскольку в последующем нет возможности использовать эту информацию в случае продолжения поиска, необходимо просматривать в некотором порядке (вообще говоря, случайном) все элементы множества, пока соответствующий элемент не будет найден, или не будет достигнут конец последовательности. В этом случае, естественной структурой данных для представления элементов множестваявляется последовательная структура данных. Ниже представлена функция, которая выполняет поиск элемента с заданным значением ключа в символьном массиве определенной длины:

function Seq_Search(A: DataArray; count:integer; key:DataKey):integer;

var j:integer;

begin

j:=1;

while (j<=count) and (key<>A[j]) j:=j+1;

if j>count then Seq_Search:=0

else Seq_Search:=j;

end; { конец последовательного поиска }

Эта функция, получая на вход последовательность элементов множества и ключ поиска key, возвращает либо значение индекса для найденного элемента массива, либо нулевое значение, когда требуемый элемент не найден.

При последовательном поиске в среднем проверяются n/2 элементов множества . В лучшем случае будет проверяться только один элемент, а в худшем - будут проверяться все n элементов. Следовательно, временная сложность алгоритма для поиска одного элемента изв худшем и среднем случае равна[14,т.3], где- число элементов множества.

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

Двоичный поиск. Процедура последовательного поиска исходит из того, что информация, полученная на предыдущих шагах алгоритма, теряется и не используется в дальнейшем. Предположим, что на элементах множествазадан линейный порядок и предикатможет возвращать значения «меньше», «равно» и «больше»4. Поскольку отношение частичного порядка “” обладает свойством транзитивности, то элементпосле выполнения операции сравнения с элементом, содержит информацию о части множества, связанного с элементомотношением порядка. Эта информация при соответствующей организации множестваможет значительно ускорить процедуру поиска. Легче всего это утверждение можно продемонстрировать на следующем примере: Пусть последовательный поиск ведется в упорядоченном (по возрастанию элементов) множестве. В этом случае, время поиска может быть сокращено за счет того, что для проверки условияв общем случае нет необходимости просматривать все элементы из. Достаточно просмотреть только часть последовательности, состоящую из элементов, меньших, пока не встретится первый элемент, больший. Однако, несмотря на такое усовершенствование, асимптотические оценки для худшего и среднего случаев остаются линейными.

Попробуем оценить время выполнения функции поиска в худшем случае с информационной точки зрения. Поскольку значение “=” предиката означает успешное завершение поиска, то информация необходимая для продолжения поиска может быть извлечена при значениях “<” или “>”. При выполнении последовательности изопераций сравнения эта информация может быть записана в виде двоичного набора, гдекодирует результат-го сравнения,. Тогда из мощностных (энтропийных) соображений имеем оценку

,

которая и является оценкой снизу числа шагов алгоритма для худшего случая.

При построении алгоритма поиска необходимо обратить внимание, что задачу можно свести к более простым задачам (подзадачам) поиска объекта на подмножествах множествас последующим объединением результатов поиска (метод «Разделяй и властвуй»). При этом, естественно полагать, что эти подмножества не должны иметь общих элементов, поскольку для элементов, входящих в пересечение мы получим избыточное представление информации, и шаги по извлечению этой информации увеличат сложность работы алгоритма. В частности, возможные значенияпредикатанаводят на мысль разбить множествона подмножествоэлементов меньших, сам элементи подмножествоэлементов большихс последующим поиском в соответствующем подмножестве. Если рекурсивно повторять этот процесс, то через определенное число шагов можно получить интересующий нас ответ. Реализация такого подхода требует указания, как выбирать элемент, относительно которого строится разбиение. Рассмотрим этот вопрос подробнее. Пусть на первом шаге наш алгоритм делит множествона два подмножестваи, число элементов в которых соответственно равнои,. Обозначим через- максимальное число обращений к предикатуалгоритма поиска на множестве изэлементов. Если по результатам сравнениянеобходимо продолжать поиск в множествеили в множестве, то справедливы соотношенияи. Появление в оценке функцииговорит о том, что оптимальная оценка (минимизирующая время работы для худшего случая) получается при выравнивании значений ее аргументов (минимизации разности). Поэтому, с позиций оптимизации времени поиска достаточно на каждом шаге делитьна примерно равные по мощности подмножестваи. Таким образом, мы приходим к методу поиска делением пополам, который называется «дихотомией». Полностью алгоритм двоичного поиска может быть описан следующим образом:

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

Выбор конкретной структуры данных, обеспечивающей реализацию алгоритма двоичного поиска, зависит от АТД. Поскольку при реализации процедуры поиска необходимо быстро уметь искать медиану, то в случае АТД (,НАЙТИ) для представления множестваподходит структура, обеспечивающая прямой доступ к элементам. Такой структурой данных является массив.

Предположим, что элементы множества перечислены в массиве согласно отношению линейного порядка. Рассмотрим реализацию двоичного поиска для этого случая:

function BinarySearch (A: DataArray; count:integer; key:DataKey):integer;

var low, high, med: integer;

found:boolean;

begin

low:=1; high:=count;

found:=false; // не найден

while (low<=high) and (not found) do

begin

med:=(low+high) div 2;

if key<A[med] then high:=med-1

else if key>A[med] then low:=med+1

else found:=true; // найден

end;

if found then BinarySearch:=med

else BinarySearch:=0; // не найден

end; { конец поиска }

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

При реализации такой стратегии поиска существенным образом используется линейный порядок на элементах множества . В случае отсутствия такого порядка, можно его ввести, отобразивв некоторое линейно упорядоченное множество5с последующей заменой поиска впоиском в. Для этого необходимо найти кодирующую биективную функцию, и вместо вычисления предикатана элементах израссматривать предикат. Например, пусть множествопредставляет собой множество ортонормированных векторов в-мерном Евклидовом пространстве. Понятно, что два любых элемента изнесравнимы между собой. Отобразим вектор, с единицей в-ой позиции в число. Тогда множество чиселявляется линейно упорядоченным и для поиска соответствующего элемента базиса можно применить стратегию двоичного поиска. Безусловно при таком подходе необходимо учитывать затраты на вычисление значений функции.

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