Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лекции / Лекция_5_Алгоритмы_поиска_ipynb_Colab

.pdf
Скачиваний:
0
Добавлен:
28.06.2026
Размер:
2.24 Mб
Скачать

Алгоритмы поиска.

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

Дано: Набор из

элементов

в которой каждый элемент представляет собой запись, которая содержит данные и

некоторый ключ

(по нему и проводится поиск) и ключ поиска .

Задача поиска поиск всех вхождений

для которых

.

Есть набор элементов последовательности (как вы догадались это кошки). Выберем в качестве ключа поиска возраст. Тогда элемент этой последовательности можно описать следующим образом:

Поиск по заданному ключу

Требования к ключам элементов

Для множества ключей должно быть определенно отношение эквивалентности «~». Причем для любых 3-х ключей (например a, b, c) должны выполняться такие условия:

Рефлексивность.

для любого ключа.

 

Симметричность. Если

, то

.

.

Транзитивность. Если

и

, то

Для пояснения в качестве ключей поиска будем как и прежде использовать возраст кошки.

Дополнительное требование для ключей поиска

Для множества ключей должно быть определенно отношение порядка «<». Причем для любых 3-х ключей (например a, b, c)

должны выполняться такие условия:

Закон трихотомии. Справедливым является одно и только одно из соотношений:

,

,

.

Закон транзитивности. Если

и

, то

.

 

 

 

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

Виды поиска

Алгоритмы поиска можно классифицировать по нескольким критериям.

1.Внутренний и внешний поиск.

2.Статический и динамический поиск.

3.Методы прямого сравнения ключей и методы использования числовых характеристик ключей.

Внешний и внутренний поиск

Статический и динамический поиск

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

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

Динамический поиск

Прямое сравнение ключей, использование числовых характеристик ключей поиска

Прямое сравнение ключей использование отношения эквивалентности. В качестве ключей используется все значение элемента Кот.

Использование числовых характеристик ключей использование отношения эквивалентности и отношение порядка меньше. В качестве ключей использует возраст кота (а это число).

Линейный(последовательный) поиск.

Сведение об алгоритме линейного поиска

Сложность по времени в наихудшем случае Затраты памяти

Принцип работы алгоритма

1. Установить начальное значения индекса (обозначим его ) равным индексу первого элемента в последовательности.

2. Получить элемент стоящий по индексу

. Возможны два случая:

a) Ключ элемента равен искомому. Вернуть индекс и завершить алгоритм. Поиск успешен.

b) Ключ элемента не равен искомому. Увеличить индекс на единицу.

. Перейти к пункту 3.

3.Проверить, индекс меньше или равен индексу последнего элемента в последовательности. Если да, то перейти к пункту 2. Если нет, то завершить алгоритм. Поиск неудачен.

Графическая иллюстрация работы алгоритма

Работа алгоритма продемонстрирована в предположении, что искомым элементом является 5

Предположим что индексация в последовательности начинается с 0. На первом шаге устанавливаем значение индекса равный 0.

. Элемент на этом индексе не равен искомому. Увеличиваем значение индекса на единицу.

Этот индекс меньше индекса последнего элемента.

. Продолжаем алгоритм.

Элемент на этом индексе не равен искомому. Увеличиваем значение индекса на единицу.

Этот индекс меньше индекса последнего элемента.

. Продолжаем алгоритм.

Элемент на этом индексе не равен искомому. Увеличиваем значение индекса на единицу.

Этот индекс меньше индекса последнего элемента.

. Продолжаем алгоритм.

Элемент на этом индексе равен искомому. Заканчиваем алгоритм. Поиск успешен.

Вычислительный эксперимент

С целью проверки асимптотического поведения реализации алгоритма линейного поиска, был проведен вычислительный эксперимент. В последовательностях разных размеров (были взяты массивы) выполнен поиск 1000 элементов. Построен график зависимости времени поиска от размеров последовательностей.

Модификация алгоритма линейного поиска

Алгоритм линейного поиска можно ускорить путем исключения пункта 3 в базовом алгоритме. Т.е. можно исключить проверку принадлежности индекса значения индексам в последовательности. Для этого стоит добавить в конец базовой последовательности элемент равный искомому.

Стоит отметить, что такая модификация имеет смысл только для последовательностей в которых вставка и удаление элемента не связаны с высокими вычислительными затратами.

Принцип работы модифицированного алгоритма линейного поиска

1.Добавить элемент (значение ключа которого равно искомому) в конец последовательности.

2.Установить начальное значение индекса (обозначим его ) равным индексу первого элемента в последовательности.

3. Получить элемент стоящий по индексу . Возможны два случая:

a) Ключ элемента равен искомому. Удалить последний элемент. Если индекс не равен индексу последнего элемента поиск успешен. В случае равенства индекса индексу последнего элемента поиск не удачен.

b) Ключ элемента не равен искомому. Увеличить индекс на единицу.

. Перейти к началу пункта 3.

Реализация алгоритма на Python

 

 

def linear_search(sequence, element):

 

"""

 

 

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

 

 

"""

 

 

for i in range(len(sequence)):

#Проходимповсеминдексампоследовательности

 

if sequence [i] ==element:

#Еслитекущийэлементравенискомому

 

return i

#Возвращаемегоиндекс

 

return -1

#Еслин чегоненашливозвращаем, -1

 

def modified linear search(sequence element):

 

"""

 

 

 

Модифицированныйалгор нейноготмпоиска

 

 

(сдобавленибарьерногоэлементавконец)

 

 

"""

 

 

 

sequence.append (element)

#1)Добавляемискомыйэлементвконец(барьер)

i=

0

 

#2)Начинаспервогоминдекса

 

 

while sequence [i] !=element:

#3)Поканевстретилиискомыйэлемент

 

i=i+

1

# Переходимкследующемуиндексу

 

sequence.pop

()

#4)Удаляемдобавленныйбарьерныйэлементиз

конца

 

if i!= len(sequence):

#5)Еслинашлиненабарьернойпозиции

 

 

return i

 

# Возвращаинднайденногоксм элемента

 

return -1

 

#6)Иначевозвращаем-1(элемннайденнт

)

Бинарный поиск.

Сведение об алгоритме бинарного поиска.

Сложность по времени в наихудшем случае

Затраты памяти

Принцип работы алгоритма

1.Сортируется последовательность в которой будет проводится поиск. Если последовательность уже отсортирована то этот шаг можно пропустить.

2.Определяется значение элемента в середине последовательности. Полученный элемент сравнивается с искомым элементом. Различают случаи:

a)Средний элемент равен искомому. Заканчиваем алгоритм. Поиск успешен.

b)Средний элемент больше искомого. Рассматриваем левую от среднего элемента часть последовательности.

c)Средний элемент меньше искомого. Рассматриваем правую от среднего элемента часть последовательности.

3.Повторяем пункт 2 до тех пор, пока не будет найден искомый элемент или не станет пустым интервал для поиска.

Графическая иллюстрация работы алгоритма

Работа алгоритма продемонстрирована в предположении, что искомым элементом является 5.

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

индекс середины последовательности

индекс левой границы

индекс правой границы

Так как в середине последовательности стоит элемент больше искомого (5 < 7) то сдвигаем правую границу.

Установив правую границу на место найденного на прошлом шаге среднего элемента повторяем вычисление среднего элемента. Это элемент с индексом 2. Его значение равно 3. И его значение меньше искомого (3 < 5). Следовательно нужно сдвинуть левую границу.

Установив левую границу на место найденного на прошлом шаге среднего элемента повторяем вычисление среднего элемента. Это элемент с индексом 3 и его значение равно 5. Он равен искомому элементу (5 == 5). Поиск окончен.

В каком случае стоит использовать бинарный поиск

Предположим что существует не отсортированная последовательность размером N элементов. В ней нужно выполнить K поисков (0 < K). При каком значении K стоит выполнить обычный линейный поиск (не сортируя массив)? При каком значении стоит отсортировать массив и использовать бинарный поиск?

Вспомогательные данные:

Сложность линейного поиска

Сложность оптимальной сортировки (например TimSort)

Сложность бинарного поиска

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

Условие перехода

Где: — Константы зависящие от ПК

Для проверки математического утверждения был проведен вычислительный эксперимент. Для одномерного массива из 1 000 000 элементов построена зависимость времени поиска от количества искомых элементов. Рассмотрен как линейный так и бинарный поиск (время сортировки массива также учитывалось). Для корректности каждый замер был повторен 100 раз и было взято усредненное время.

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

Реализация алгоритма на Python

Интерполяционный поиск

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

Сложность по времени в наихудшем случае

Принцип работы алгоритма

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

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

Интерполяция

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

Имеющиеся данные вида

точки данных, базовые точки. Где

.

узлы интерполяции

шаг интерполяционной сетки

Задача интерполяции состоит в нахождении такой функции , что

.

интерполирующая функция

Разные интерполяционные функции

Линейная интерполяция

Пожалуй наиболее простым методом интерполяции по двум точкам (в общем случае интерполяцию можно проводить по N точкам) является линейная интерполяция. В таком случае в качестве интерполирующей функции используется уравнение прямой по двум точкам. Довольно часто алгоритм интерполяционного поиска использует именно линейную интерполяцию.

Уравнение прямой по двум точкам (2-х мерная система координат):

Отсюда можно получить:

Требуемые прямые и обратные зависимости:

Использование линейной интерполяции в алгоритме

Использование линейной интерполяции в алгоритме

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

где

индекс в последовательности,

значение элемента по этому индексу. Используем линейную интерполяцию по двум

 

точкам. Предсказание индекса на котором стоит искомый элемент (обозначим его

) будем проводить по обратной зависимости.

Выберем две точки для построения интерполяционной прямой. Обозначим их как

и соответственно. В таком случае индекс

искомого элемента вычисляется по формуле:

 

 

 

 

 

 

 

 

Принцип работы алгоритма

1.Сортируется последовательность в которой будет проводится поиск. Если последовательность уже отсортирована то этот шаг можно пропустить.

2.В качестве начальных точек (левая и правая) выбираем первый и последний элемент последовательности.

3.Определяется значение индекса по формуле линейной интерполяции. Получаем элемент по этому индексу. Полученный

элемент сравнивается с искомым элементом. Различают случаи: a) Элемент равен искомому. Заканчиваем алгоритм. Поиск успешен. b) Элемент больше искомого. Сдвигаем правую точку. Новое значение (найденный индекс 1). c) Элемент меньше искомого. Сдвигаем левую точку. Новое значение (найденный индекс 1).

4. Повторяем пункт 3 до тех пор, пока не будет найден искомый элемент или не станет пустым интервал для поиска.

Графическая иллюстрация работы алгоритма

Работа алгоритма продемонстрирована в предположении, что искомым элементом является 5.