- •2. Разработка программ с графическим интерфейсом пользователя с помощью mfc, но без AppWizard.
- •4. Класс двунаправленного списка.
- •5. Алгоритм поиска. Хеширование. Класс хеш-таблицы.
- •Хеширование
- •7. Параметризированная функция бинарного поиска в массиве.
- •8. Кодування символів, алгоритм Хаффмана.
- •6. Построение класса параметризованного ограниченного массива.
- •3. Построение параметризованного класса очереди.
- •9. Збалансовані дерева. Включення в збалансоване дерево. Два випадки балансування.
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 практические задачи – выбрать хеш-