
labs&konspeckts / SP_ukr / asm_10
.docМетоди пошуку елементів в таблиці Мета роботи: вивчити основні методи пошуку елемента в таблиці.
Теоретичні
відомості
Лінійний пошук елементів
таблиці.
Лінійний пошук можна виконувати як в
упорядкованих так і в невпорядкованих
таблицях.
Метод полягає в послідовному
порівнянні ключа шуканого елемента з
ключами елементів таблиці до збігу або
до досягнення кінця таблиці.
При
роботі з упорядкованою таблицею факт
відсутності елементу може бути
встановлений без перегляду всієї
таблиці.
Алгоритм лінійного пошуку
в невпорядкованій таблиці
1 Установка
індексу першого елемента таблиці.
2
Порівняння ключа шуканого елемента з
ключем елемента таблиці.
3 Якщо ключі
рівні, перейти на обробку ситуації
"пошук успішний", інакше на 4.
4
Інкремент індексу елемента таблиці.
5
Перевірка кінця таблиці.
6 Якщо вичерпані
всі елементи таблиці, перейти до обробки
ситуації "пошук невдалий", інакше
на блок 2.
Алгоритм лінійного пошуку
в впорядкованої
по зростанню таблиці.
1
Установка індексу першого елемента
таблиці.
2 Порівняння ключа шуканого
елемента з ключем елемента таблиці.
3
Якщо ключі рівні, перейти на обробку
ситуації "пошук вдалий", інакше на
4.
4 Якщо шуканий ключ менше ключа
елемента таблиці, перейти на обробку
ситуації "пошук невдалий", інакше
на 5.
5 Інкремент індексу елемента
таблиці.
6 Перевірка кінця таблиці.
7
Якщо вичерпані всі елементи таблиці,
перейти до обробки ситуації
"Пошук
невдалий", інакше на блок 2.
Двійковий
пошук елементів таблиці
При
великих обсягах таблиць (більше 50
елементів) ефективніше використовувати
двійковий
пошук, при якому визначається адреса
середнього елемента таблиці, з
ключовою
частиною якого порівнюється ключ
шуканого елемента. При збігу
ключів
пошук вдалий, а при розбіжності з
подальшого пошуку виключається
та
половина елементів, в якій шуканий
елемент знаходитися не може.
Така
процедура повторюється, поки довжина
частини таблиці не стане
рівною
0.
Алгоритм двійкового
пошуку
1 Завантаження початкового
(Ан) і кінцевого (Ак) адрес таблиці
2
Визначення адреси середнього елемента
таблиці (Аср)
3 Порівняння шуканого
ключа з ключовою частиною середнього
елемента таблиці
4 При рівності ключів
пошук вдалий
Якщо шуканий ключ
менше ключа середнього елемента, то Ак
= Аср, перехід на 5
Якщо шуканий
ключ більше ключа середнього елемента,
то Ан = Аср + довжина елемента,
перехід
на 5
5 Порівняння Ан і Ак. Якщо Ан =
Ак, пошук невдалий, інакше перехід на
2
При визначенні адреси середнього
елемента слід виконати наступні
дії:
-
Обчислити довжину таблиці Ак-Ан
-
Визначити число елементів таблиці
(Ак-Ан) / Lе, де Lе-довжина елемента
-
Визначити довжину половини таблиці
((Ак-Ан) / Lе) / 2 * Lе
- Визначити
адресу середнього елемента таблиці Аср
= Ан + ((Ак-Ан) / Lе) / 2 * Lе
Теорія. Відкрите
Хешування
Хеш-таблиця - це звичайний
масив з незвичайною адресацією, що
задається хеш-функцією.
Наприклад,
на hashTable рис. 1 - це масив з 8 елементів. Кожен
елемент представляє собою покажчик на
лінійний список, який зберігає
числа. Хеш-функція в цьому прикладі
просто ділить ключ на 8 і використовує
залишок як індекс в таблиці. Це дає
нам числа від 0 до 7. Оскільки для
адресації в hashTable нам і потрібні числа
від 0 до 7, алгоритм гарантує допустимі
значення індексів.
Хешування
корисно, коли широкий діапазон можливих
значень повинен бути збережений в малому
обсязі пам'яті, і потрібен спосіб
швидкого, практично довільного
доступу. Хеш-таблиці часто застосовуються
в базах даних, і, особливо, в мовних
процесорах типу компіляторів і асемблерів,
де вони витончено обслуговують таблиці
ідентифікаторів. У таких програмах,
таблиця - найкраща структура даних.
Так як кожен доступ до таблиці повинен
бути проведений через хеш-функцію,
функція повинна задовольняти двом
вимогам: Вона повинна бути швидкою, і
вона повинна породжувати хороші ключі
для розподілу елементів по таблиці. Остання
вимога мінімізує колізії (випадки, коли
два різні елементи мають однакове
значення хеш-функції) і запобігає
випадок, коли елементи даних з близькими
значеннями потрапляють тільки в одну
частину таблиці.
Рис. 1:
Хеш-таблиця
Щоб вставити в таблицю
новий елемент, ми хешуємо ключ, щоб
визначити список, в який його потрібно
додати, потім вставляємо елемент у
початок цього списку. Наприклад, щоб
додати 11, ми ділимо 11 на 8 і отримуємо
залишок 3. Таким чином, 11 слід розмістити
в списку, на початок якого вказує
hashTable . Щоб знайти число, ми його
хешуємо проходимо по відповідному
списку. Щоб видалити число, ми знаходимо
його і видаляємо елемент списку, його
містить.
При додаванні елементів
в хеш-таблицю виділяються шматки
динамічної пам'яті, які організовуються
у вигляді пов'язаних списків, кожен з
яких відповідає входу хеш-таблиці. Цей
метод називається зв'язуванням.
Метод поділу (розмір таблиці hashTableSize -
просте число). Цей метод використаний
в прикладі нижче. Хешірующее значення
hashValue, що змінюється від 0 до (hashTableSize -
1), так само залишку від ділення ключа
на розмір хеш-таблиці. Ось як це може
виглядати:
makehashkey macro value, hashkey
xor
ax, ax
xor dx, dx
mov ax, value
div
hash_table_size
mov hashkey, dx; залишок від
ділення зберігається в dx
endm
pushtotable
macro value; запис значення в хеш-таблицю
makehashkey
value, cx; отримуємо хеш-ключ (індекс для
хеш-таблиці)
xor si, si
mov dx, cx
l3:
add si,
2; обчислюємо зсув в хеш-таблиці за
індексом
loop l3
mov bx, hash_table [si]; записуємо
значення елемента хеш-таблиці (посилання
на список)
mov dx, value
mov [bx], dx записуємо
в список значення value
endm
Завдання на лабораторну роботу: У роботі реалізувати лінійний, бінарний і хеш-пошук. Для перевірки роботи алгоритму використовувати формат таблиць з лаб.раб. 9 У зв'язку з обмеженими можливостями на рівні асемблера (динамічне виділення пам'яті, пов'язані списки) нижче наведено приклад створення хеш-таблиці на 3 елементи. .386 i equ 3 ASSUME CS: CODE, DS: DATA ; ------------------------------------------------- ------ v_table struc; визначаємо список на який посилається хеш-таблиця v dw 0; кількість елементів у списку 1 v_table ends ; ------------------------------------------------- ------ DATA SEGMENT use16 value dw 2 hash_table_size dw i; визначаємо розмір таблиці hash_table dw 0 "dup (i); виділяємо пам'ять під хеш-таблицю mytable v_table <1>; списки на які посилається хеш-таблиця v_table <2>; значення елементів за замовчуванням 0 v_table <0>; DATA ENDS ; ------------------------------------------------- ------ CODE SEGMENT use16 beg: mov ax, data mov ds, ax lea si, hash_table; завантажуємо зсув хеш-таблиці mov cx, hash_table_size; записуємо в лічильник розмір таблиці mov di, 0 mov bx, offset mytable; завантажуємо зсув таблиці списків l1: mov [si], bx; записуємо в хеш-таблицю посилання (зміщення) кожного зі списків inc si inc si add bx, 2 loop l1 xor ax, ax xor dx, dx mov ax, value div hash_table_size mov cx, dx xor si, si mov dx, cx l3: add si, 2 loop l3 mov bx, hash_table [si] mov dx, [bx]; відмінність тільки в тому що значення витягується зі списків mov ah, 4Ch int 21h CODE ENDS END beg