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

5. Алгоритм поиска. Хеширование. Класс хеш-таблицы.

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

Большинство задач поиска сводится к простейшей — к поиску в массиве элемента с заданным значением. Рассмотрим именно эту задачу. Пусть требуется найти элемент Х в массиве А. В данном случае известно только значение разыскиваемого элемента, никакой дополнительной информации о нем или о массиве, в котором производится поиск, нет. Наверное, единственным способом является последовательный просмотр массива и сравнение значения очередного рассматриваемого элемента массива с X. Напишем фрагмент: for(int i=0;i<=n;i++) if (a[i]=X) k=i;

А если исключить лишние проверки? Совпадение найдено, зачем делать "пустую" работу?

for(int i=0;i<=n;i++) if (a[i]=X) { k=i; i=n; }

Очевидно, что число сравнений зависит от местонахождения искомого элемента. В среднем количество сравнений равно (N + 1) div 2, в худшем случае, когда элемента нет в массиве, N сравнений. Эффективность поиска — O(N).

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

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

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

Программная реализация бинарного поиска может иметь следующий вид.

void search(int x)

{int i,j,m;

bool f;

i=0; j=N;//На 1-ом шаге рассматривается весь массив.

f=false; //Признак того, что x не найден.

while ((i<=j) && (!f)

{m = (i+j) / 2;

if (A[m]=x) f=true //Элемент найден, поиск прекращается.

else if A[m]<x i:=m+l //Исключаем из рассмотрения левую часть А.

else j:=m-l {Правую часть.}}}

Предложим еще одну, рекурсивную, реализацию изучаемого поиска.

Int Search (int i,j)

{ //Массив А и переменная Х глобальные величины

int m;

If (i>j) return -1else

{m=(i+j)/2; If A[m]<X Search(m+1,j) Else

If A[m]>X Search(i,m-l) Else return m;}}

Хеширование

Выше описанные 2 метода основаны на сравнении данного аргумента К с ключами в таблице или на использовании его цифр для управления процессом разветвления. Третий путь – отказаться от поиска по данным и выполнить арифметические действия над К, позволяющие вычислить некоторую функцию f(K). Последняя укажет адрес в таблице, где хранится К и связанная с ним информация. Недостаток – нужно заранее знать содержимое таблицы.. Добавив всего одно значение может придется начать работу с нуля. Может случится что найдутся различные ключи Ki<>Kj имеющие одинаковые значение хеш-функций f(Ki)<>f(Kj). Такое событие называется коллизией. Для использования хеширования программист должен решить 2 практические задачи – выбрать хеш-

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