Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Otvetu.docx
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
29.7 Кб
Скачать
  1. Алгоритм поиска

Общая классификация алгоритмов поиска

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

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

Так же методы поиска можно разделить на методы, использующие истинные ключи и на методы, работающие по преобразованным ключам. В данном случае "ключем" называют то значение, которое мы ищем.

Поиск в колоде карт - поиск по истинным ключам, то есть имеете дело с тем, что есть. Поиск в словаре - поиск по преобразованным ключам, так как все слова отсортированы в алфавитном порядке, то есть массив значений изменен перед началом поиска. Этот порядок создан специально для облегчения поиска и вовсе не является естественным для списка слов!

Кстати, привычный нам алфавитный порядок слов, не всегда казался людям естественным и является изобретением не очень древним.

Ну и еще вариант классификации - методы основанные на сравнении самих значений и методы, основанные на их цифровых свойствах. Так называемые методы хэширования.

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

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

f("крестовая дама") = 5 , а f("туз пик")=12

То есть, подставив в функцию искомое значение, мы получаем местоположение этого значения в нашем массиве. Вот здорово! Это же самый что ни на есть ПРЯМОЙ доступ , по сравнению с ПОСЛЕДОВАТЕЛЬНЫМ перебором всех ( или некоторых ) значений в искомом массиве.

Этот метод и называется методом хэширования. Все бы хорошо, но вот беда, функция f(К) должна определять ОДНОЗНАЧНОЕ соответствие для каждого значения в массиве, а находить подобные функции довольно сложно.

Подробное рассмотрение алгоритмов

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

Перед Вами колода игральных карт, в ней , как правило, 54 карты ( ну или 36 ). Карты лежат в беспорядке. Необходимо найти определенную карту, например пикового короля. Что Вы предпримете? Думаю, что догадаться нетрудно, первое, что приходит в голову, это последовательно перебирать все карты, до тех пор пока нужная не найдется. При самом плохом стечении обстоятельств Вам придется перебрать все карты в колоде , что на самом деле не так долго, если честно.

Попробуем немного изменить условие. Искать нам надо не карту, а конверт с определенным адресом. Конвертов этих перед Вами лежит немерянное количество, если окинуть взглядом заваленные столы, ну несколько сотен как минимум. Нет, нет, не пожимайте удивленно плечами, задача не надуманная, а самая что ни на есть реальная. Если вдруг кто-нибудь ( а мир так удивительно тесен! ) знаком с Константиновым Николаем Николаевичем, тот скорее всего знаком с этой задачей не понаслышке. Итак, я отвлеклась, перед нами несколько сотен конвертов с именами, нужно найти вполне определенный конверт. Способ, только что опробованный на колоде карт, очень скоро утомит. Вряд ли кто в этом сомневается, не правда ли? :о)

А вот если предварительно все эти конверты разложить в алфавитном порядке, то дальнейшая работа по нахождению вполне определенного имени уже не представляется такой ужасной! Конечно, на сортировку необходимо затратить вполне определенные силы и время, но они окупятся при многоразовом поиске, вот что самое главное

Вспомнив пример с картами, отметим, что в том случае тратить время на предварительную сортировку колоды вряд ли стоит...

Итак, мы можем сделать первый и очень важный вывод - оптимальность метода поиска зависит от размера массива, в котором мы ищем! Прямой перебор всех значений прост в понимании, легок в исполнении и достаточно быстр на малых массивах данных. Насчет легкости и простоты , это не лирика, это весомый аргумент, ведь Вам после того, как будет выбран определенный метод, необходимо еще формализовать его и закодировать. В итоге программиста инетересует код. Не будем об этом забывать.

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

Ну что же, с задачей поиска при малом количестве значений мы разобрались, она достаточно тривиальна. Давайте займемся поиском в о-о-очень длинном массиве... Это гораздо интереснее. Итак, приняв все вышесказанное за истину, мы отсортировали наш массив. Все значения лежат в некотором порядке. Можно искать! И, собственно, что?... Как искать-то?

Существует несколько классических способов поиска значения в отсортированном массиве. Мы рассмотрим три способа. Они были предложены в 60-х годах и мало изменились в наше время. Один из них очень известный, ведь Вам наверняка приходилось слышать такие названия как "метод дихотомии", "бинарного дерева" или "метод половинного деления", что собственно одно и тоже. Вот с него и начнем.

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