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

Мал. 2 Організації таблиці ідентифікатора з використанням хеш-адресації

На мал.2 проілюстрований метод організації таблиць ідентифікаторів з використовуванням хеш-адресації. Трьом різним ідентифікаторам A1, А2, A3 відповідають на малюнку три значення хеш-функції n1, n 2, n З. У комірки, адресовані n1, n2, nЗ, поміщають інформацію про ідентифікатори A1, А2, A3. При пошуку ідентифікатора A3 обчислюється значення адреси n3 і вибираються дані із відповідної комірки таблиці.

Цей метод досить ефективний, оскільки як час розміщення елемента в таблиці, так і час його пошуку визначаються тільки часом, що витрачається на обчислення хеш-функції, яке в загальному випадку незрівнянно менше часу, необхідного для виконання багаторазових порівнянь елементів таблиці. Метод має два очевидних недоліки. Перший з них - неефективне використування обсягу пам'яті під таблицю ідентифікаторів: розмір масиву для її зберігання повинен відповідати області значень хеш-функції, в той час як реально збережених у таблиці ідентифікаторів може бути істотно менше. Другий недолік - необхідність відповідного розумного вибору хеш-функції. Цьому істотного питанню присвячені наступні два підпункти.

Побудова таблиць ідентифікаторів на основі хеш-функцій

Існують різні варіанти хеш-функцій. Отримання результату хеш-функції - «хешування» - зазвичай досягається за рахунок виконання над ланцюжком деяких простих арифметичних і логічних операцій. Найпростішою хеш-функцією для символу є код внутрішнього представлення в комп'ютері літери символу. Цю хеш-функцію можна використовувати і для ланцюжка символів, вибираючи перший символ у ланцюжку. Так, якщо двійкове ASCII-представлення символу А є двійковий код 001000012, то результатом хешування ідентифікатора АТable буде код 001000012.

Хеш-функція, запропонована вище, очевидно не задовільна: при використанні такої хеш-функції виникне проблема - двом різним ідентифікаторам, які починаються з однієї і тієї ж букви, відповідатиме одне і те ж значення хеш-функції. Тоді при хеш-адресації в одну клітинку таблиці ідентифікаторів з одного й того ж адресою повинні бути поміщені два різних ідентифікатора, що явно неможливо. Така ситуація, коли двом або більше ідентифікаторам відповідає одне і те ж значення функції, називається колізією.

Природно, що хеш-функція, яка припускає колізії, не може бути безпосередньо використана для хеш-адресації в таблиці ідентифікаторів. Причому достатньо отримати хоча б один випадок колізії по всій множині ідентифікаторів, щоб такою хеш-функцією не можна було користуватися безпосередньо. Але в прикладі взята сама елементарна хеш-функція. А чи можливо побудувати хеш-функцію, яка б повністю виключала виникнення колізій? Очевидно, що для повного виключення колізій хеш-функція повинна бути взаємно однозначною: кожному елементу з області визначення хеш-функції має відповідати одне значення з її множини значень, і кожному значенню з множини значень цієї функції повинен відповідати тільки один елемент з області її визначення. Тоді будь-яким двом елементам довільним з області визначення хеш-функції будуть завжди відповідати два різних її значення. Теоретично для ідентифікаторів таку хеш-функцію побудувати можна, так як і область визначення хеш-функції (всі можливі імена ідентифікаторів), і область її значень (цілі невід’ємні числа) є нескінченними рахунковими множинами. Теоретично можна організувати взаємно однозначне відображення одної рахункової множини на іншу, але практично це зробити виключно складно.

Практично існує обмеження, що робить створення взаємно однозначної хеш-функції для ідентифікаторів неможливим. Справа в тому, що в реальності область значень будь-якої хеш-функції обмежена розміром доступного адресного простору в даній архітектурі комп'ютера. При організації хеш-адресації значення, яке використовується в якості адреси таблиці ідентифікаторів, не може виходити за межі, задані розрядністю адреси комп’ютера. Множина адрес будь-якого комп'ютера з традиційною архітектурою може бути велика, але завжди звичайно, тобто обмежена. Організувати взаємно однозначне відображення нескінченної кількості на кінцеве навіть теоретично неможливо. Можна врахувати, що довжина прийому до уваги частини імені ідентифікатора в реальних компіляторах також практично обмежена - зазвичай вона лежить в межах від 32 до 128 символів (тобто і область визначення хеш-функції кінцева). Але і тоді кількість елементів в кінцевій множині, що становить область визначення функції, буде перевищувати їх кількість в кінцевій множині області значень функції (кількість всіх можливих ідентифікаторів все одно більше кількості допустимих адрес в сучасних комп'ютерах). Таким чином, створити взаємно однозначну хеш-функцію практично ні в якому варіанті неможливо. Отже, неможливо уникнути виникнення колізій.

Для вирішення проблеми колізії можна використовувати багато способів. Одним з них є метод рехеширування (або розстановка).Згідно з цим методом, якщо для елемента А адреса h(A), обчислений за допомогою хеш-функції h, вказує на вже зайняту комірку, то необхідно обчислити значення функції n1=h1(A) і перевірити зайнятість комірки за адресою n1. Якщо і вона зайнята, то обчислюється значення h2(A) і так до тих пір, поки або не буде знайдена вільна комірка, або чергове значення h1(A) збіжиться з h(A). В останньому випадку вважається, що таблиця ідентифікаторів заповнена, і місця в ній більше немає - видається інформація про помилку розміщення ідентифікатора в таблиці.

Таку таблицю ідентифікаторів можна організувати за наступним алгоритмом розміщення елементу:

Крок 1.Обчислити значення хеш-функції n=h(A) для нового елемента А. Крок 2. Якщо комірка за адресою n порожня, то помістити в неї елемент А і завершити алгоритм, інакше i:=1 і перейти до кроку 3.

Крок 3. Обчислити n1=h1(A). Якщо комірка за адресою ni порожня, то помістити в неї елемент А і завершити алгоритм, інакше перейти до кроку 4. Крок 4. Якщо n=n1 то повідомити про помилку і завершити алгоритм, інакше i:= i + 1 і повернутися до кроку 3.

Тоді пошук елемента А в таблиці ідентифікаторів, організованої таким чином, буде виконуватися за наступним алгоритмом:

Крок 1. Обчислити значення хеш-функції n= h(A) для шуканого елемента А. Крок 2. Якщо комірка за адресою n порожня, то елемент не знайдений, алгоритм завершено, інакше порівняти ім'я елемента в комірці n з ім'ям шуканого елемента А. Якщо вони збігаються, то елемент знайдений і алгоритм завершений, інакше i:=1 і перейти до кроку 3.

Крок 3. Обчислити n1=h1(A). Якщо комірка за адресою n, пуста, або n=n1 то елемент не знайдений і алгоритм завершений, інакше порівняти ім'я елемента в комірці n, з ім'ям шуканого елемента А. Якщо вони збігаються, то елемент знайдений і алгоритм завершений, інакше i: = i + 1 і повторити крок 3.

Алгоритми розміщення та пошуку елемента схожі по виконуваних операціях. Тому вони будуть мати однакові оцінки часу, необхідного для їх виконання.

При такій організації таблиць ідентифікаторів у разі виникнення колізії алгоритм розміщує елементи в порожніх клітинках таблиці, вибираючи їх визначеним чином. При цьому елементи можуть попадати в комірки з адресами, які потім будуть збігатися зі значеннями хеш-функції, що призведе до виникнення нових, додаткових колізій. Таким чином, кількість операцій, необхідних для пошуку або розміщення в таблиці елемента, залежить від заповнювання таблиці.

Для організації таблиці ідентифікаторів за методом рехеширування необхідно визначити всі хеш-функції h1 для всіх i. Найчастіше функції h1 визначаються як деякі модифікації хеш-функції h. Наприклад, найпростішим методом обчислення функції h1(A) є її організація у вигляді

h1(A)=(h(A) + р1) mod Nm, де р1- деяке обчислюване ціле число, a Nm - максимальне значення з області значень хеш-функції h. У свою чергу, найпростішим підходом тут буде покласти pi = i. Тоді отримуємо формулу

h1(A)=(h(A) + i) mod Nm. У цьому випадку при збігу значень хеш-функції для будь-яких елементів пошук вільного осередку в таблиці починається послідовно від поточної позиції, заданої хеш-функцією h(A).

Цей спосіб не можна визнати особливо вдалим - при збігу хеш-адрес елементи в таблиці починають групуватися навколо них, що збільшує число необхідних порівнянь при пошуку і розміщенні. Середній час пошуку елемента в такій таблиці в залежності від кількості операцій порівняння можна оцінити таким чином [17]:

Тn = O((1-Lf/2)/(1-Lf)).

Тут Lf - (load factor) ступінь заповнювання таблиці ідентифікаторів – відношення числа зайнятих клітинок N таблиці до максимально допустимому числу елементів у ній: Lf = N / Nm.

Розглянемо як приклад ряд послідовних елементів таблиці: n1, n2, n3, n4, n5 і ряд ідентифікаторів, які треба розмістити в ній: А1, А2, А3, А4, А5 за умови, що h(А1) = h(А2) = h(А5) = n1; h(А3) =n2; h (А4) = n4. Послідовність розміщення ідентифікаторів у таблиці при використанні простого методу рехеширування показана на Мал.3. У підсумку після розміщення в таблиці для пошуку ідентифікатора А1 потрібно 1 порівняння, для А2 - 2 порівняння, для А3 - 2 порівняння, для А4 - 1 порівняння і для А5 - 5 порівнянь.