lek_04.ppt
- Количество слайдов: 53
Методи пошуку Лекція з курсу «Структури даних» Час – 2 год
План • Послідовний пошук • Бінарний пошук • Пошук за Фібоначчі • Інтерполяційний пошук • Пошук за бінарним деревом • Пошук по бору • Пошук хешуванням • Алгоритми пошуку словесної інформації
Предмети (об'єкти), що складають множину, називаються її елементами. Елемент множини буде називатися ключем і позначатися латинською буквою ki з індексом, що вказує номер елементу. Алгоритми пошуку можна розбити на наступні групи
Задача пошуку. Нехай задано множину ключів {k 1, k 2, k 3, . . . kn}. Необхідно відшукати в множині ключ ki. Пошук може бути завершений у двох випадках: • ключ в множині відсутній; • ключ знайдений в множині.
Послідовний пошук
В послідовному пошуку вихідну множину не впорядковано, тобто є довільний набір ключів {k 1, k 2, k 3, . . . kn}. Метод полягає в тому, що шуканий ключ ki послідовно порівнюється з усіма елементами множини. При цьому пошук закінчується достроково, якщо ключ знайдений.
Алгоритм пошуку зводиться до послідовності таких кроків: Крок S 1. [Початкова установка. ] Встановити i: = 1. Крок S 2. [Порівняння. ] Якщо k = ki алгоритм закінчується вдало. Крок S 3. [Просування. ] Збільшити i на 1. Крок S 4. [Кінець файлу? ] Якщо i
Бінарний пошук
В бінарному пошуку вихідна множина повинна бути впорядкованою за зростанням, іншими словами, кожен подальший ключ більше попереднього, тобто k 1 ≤ k 2 ≤ k 3 ≤. . . ≤ kn. Шуканий ключ порівнюється з центральним елементом множини, якщо він менше центрального, то пошук продовжується в лівій підмножині, в іншому випадку - у правій.
Медіаною послідовності з n елементів вважається елемент, значення якого менше (або дорівнює) половини n елементів і більше (або дорівнює) іншої половини. Задачу пошуку медіани прийнято пов'язувати з сортуванням, так як медіану завжди можна знайти наступним способом: відсортувати n елементів і потім вибрати середній елемент. В алгоритмі К. Хоара для знаходження медіани використовується операція поділу, що застосовується при швидкому сортуванні, з L=1, R=n і з a[k], обраними в якості розділяючого значення x. Отримуються значення індексів i та j.
1) розділяюче значення x було занадто малим; в результаті межа між двома частинами нижче шуканого значення k. Процес поділу слід повторити для елементів a[i], . . . , a[R] ; Рис. 2. Зсув межі вліво 2) обрана межа x була занадто велика. Операцію розбиття слід повторити на підмасиві а [L], . . . , а [j]; Рис. 3. Зсув межі вправо
3) значення k лежить в інтервалі j
Пошук за Фібоначчі
У цьому пошуку аналізуються елементи, що знаходяться в позиціях, рівних числам Фібоначчі. Числа Фібоначчі отримують за наступним правилом: кожне наступне число дорівнює сумі двох попередніх чисел, наприклад: {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, . . . }. Пошук триває до тих пір, поки не буде знайдений інтервал між двома ключами, де може розташовуватися шуканий ключ. Пошук за Фібоначчі призначається для пошуку аргументу k серед розташованих в порядку зростання ключів К 1 <К 2 <. . . <Кn.
Для зручності опису передбачається, що n+1 є число Фібоначчі Fk+1. Підходящою початковою установкою даний метод можна зробити придатним для будьякого n. F 1. [Початкова установка. ] Встановити i: =Fk, p: =Fk-1, q=Fk-2. (В алгоритмі p і q позначають послідовні числа Фібоначчі. ) F 2. [Порівняння. ] Якщо К<Кi, то перейти на F 3, якщо К>Кi, то перейти на F 4; якщо К=Ki, алгоритм закінчується вдало. F 3. [Зменшення i. ] Якщо q=0, алгоритм закінчується невдало. Якщо q≠ 0, то встановити i: =i-q, замінити (p, q) на (q, q-p) і повернутися на F 2. F 4. [Збільшення i. ] Якщо p=1, алгоритм закінчується невдало. Якщо р≠ 1, встановити i: =i+q, p: =p-q, q: =q-p і повернутися на F 2.
Інтерполяційний пошук
Початкова множина повинна бути впорядкованою за зростанням. Первісне порівняння здійснюється на відстані кроку d, який визначається за формулою: де i – номер першого розглянутого елемента; j – номер останнього елемента, що розглядається; К - шуканий ключ; Кi, Кj - значення ключів в позиціях i та j; [ ] - ціла частина числа.
Ідея методу полягає в наступному: крок d змінюється після кожного етапу за формулою наведеною вище (рис. 5) Рис. 5. Схема інтерполяційного пошуку Алгоритм закінчує роботу при d=0, при цьому аналізуються сусідні елементи, після чого приймається остаточне рішення про результати пошуку. Цей метод ефективно працює, якщо вихідна множина являє собою арифметичну прогресію або множину, наближену до неї.
Пошук за бінарним деревом
Дерево двійкового пошуку для множини чисел S - це розмічене бінарне дерево, кожній вершині якого поставлене у відповіднісь число з множини S, причому всі позначки задовольняють наступного простому правилу: «якщо більше - направо, якщо менше - наліво» .
Наприклад, для набору чисел {7, 3, 5, 2, 8, 1, 6, 10, 9, 4, 11} вийде бінарне дерево (рис. 6). Для того щоб правильно врахувати повторення чисел, можна ввести додаткове поле, яке буде зберігати кількість входжень для кожного числа. Рис. 6. Дерево двійкового пошуку
Бінарне дерево, відповідне бінарному пошуку серед n записів, можна побудувати наступним чином: при n=0 дерево зводиться до вузла 0. В іншому випадку кореневим вузлом є [n/2], ліве піддерево відповідає бінарному дереву з [n/2]-1 вузлами, а праве - дереву з [n/2] вузлами і числами у вузлах, збільшеними на [n/2] (рис. 7).
Число вузлів, породжених окремим вузлом (число піддерев даного кореня), називається його ступенем. Вузол з нульовим ступенем називають листом, або кінцевим вузлом. Максимальне значення ступеня всіх вузлів даного дерева називається ступенем дерева.
Алгоритм пошуку за бінарним деревом: спочатку аргумент пошуку порівнюється з ключем, що знаходяться в корені. Якщо аргумент збігається з ключем, пошук закінчений, якщо не збігається, то у випадку, коли аргумент виявляється менше ключа, пошук триває в лівому піддереві, а у випадку, коли більше ключа, - у правому піддереві. Збільшивши рівень на 1, повторюють порівняння, вважаючи поточний вузол коренем. Використання структури бінарного дерева дозволяє швидко вставляти і видаляти записи і проводити ефективний пошук по таблиці. Така гнучкість досягається додаванням в кожен запис двох полів для зберігання посилань.
Нехай дано бінарне дерево пошуку (рис. 8). Потрібно за бінарним деревом відшукати ключ SAG. При перегляді від кореня дерева видно, що за першою літерою латинського алфавіту назва SAG більша ніж САР. Отже, подальший пошук будемо здійснювати в правій гілці. Це слово більше, ніж PIS, значить, знову йдемо вправо; воно менше, ніж TAU, - йдемо вліво; воно менше, ніж SCO, потрапляємо в вузол 8. Таким чином, назва SAG повинна знаходитися у вузлі 8.
При цьому вузли дерева мають структуру, представлену в таблиці. Структура вузлів дерева Ключ Інформаційна частина Вказівник на ліве піддерево Вказівник на праве піддерево (может бути відсутня) LLINK RLINK KEY
Приклад. Нехай дана вихідна множина ключів {2, 4, 5, 6, 7, 9, 12, 14, 18, 21, 24, 25, 27, 30, 32, 33, 34, 37, 39}. Початкове множина ключів повинно бути впорядковано за зростанням. Шукаємо ключ К = 24.
Перетворення довільного дерева в бінарне. Впорядковані дерева ступеня 2 називаються бінарними деревами. Бінарне дерево складається з скінченної множини елементів (вузлів), кожен з яких або порожній, або складається з кореня (вузла), пов'язаного з двома різними бінарними деревами, так званими лівим і правим піддеревами кореня. Дерева, у яких d>2, називаються d-арними.
Перетворення довільного дерева з впорядкованими вузлами в бінарне дерево зводиться до наступних дій. Спочатку в кожному вузлі вихідного дерева викреслюємо всі гілки, окрім найлівіших. Після цього в отриманому графі з'єднуємо горизонтальними гілками ті вузли одного рівня, які є «братами» у вихідному дереві. (Якщо кілька вузлів мають спільного предка, то такі вузли називаються «братами» ). В отриманому таким чином дереві лівим нащадком кожного вузла x вважається той, що безпосередньо знаходиться під ним вузол (якщо він є), а в якості правого нащадка - сусідній справа «брат» для x, якщо такий є.
На рис. 10 показані етапи перетворення таким способом деякого d-арного дерева в бінарне. Перехід від довільного дерева до його бінарного еквіваленту не тільки полегшує аналіз логічної структури, але також спрощує машинне представлення, тобто фізичну структуру дерева.
Рис. 10. Етапи перетворення d-арного дерева в бінарне.
Збалансоване бінарне дерево. Бінарне дерево називається збалансованим (B-balanced), якщо висота лівого піддерева кожного вузла відрізняється від висоти правого не більше ніж на 1.
Розглянемо наступну структуру вузлів збалансованого бінарного дерева (табл. 2). Структура вузлів збалансованого дерева Ключ Вказівник на ліве піддерево Вказівник на праве піддерево Показник збалансованості вузла KEY LLINK RLINK В В - показник збалансованості вузла, тобто різниця висот правого і лівого піддерева (В = +1; 0; -1). При відновленні балансу дерева по висоті враховується показник В.
Рис. 12. Дерева з показниками збалансованості вузлів Символи +1, 0, -1 на рис. 12 вказують, що ліве піддерево вище правого, піддерева рівні по висоті, праве піддерево вище лівого.
Пошук по бору
Особливу групу методів пошуку утворює представлення ключів у вигляді послідовності цифр і букв. Розглянемо, наприклад, наявні в багатьох словниках літерні висічки. Тоді по першій букві даного слова можна відшукати сторінки, що містять всі слова, що починаються з цієї літери. Розвиваючи ідею політерної висічки, одержимо схему пошуку, засновану на індексації в структурі бору (термін використовує частину слова вибірка).
Бор є m-арное дерево. Кожен вузол рівня h - це множина всіх ключів, що починаються з певної послідовності з h літер. Вузол визначає m-шляхове розгалуження в залежності від (h+1)-ї літери. Структуру бору можна представити у вигляді табл. 3. Вузли Символи 1 2 3 … N Пробіл ( ) У першому вузлі записується перша буква або цифра ключа. У другому вузлі до неї додається ще один символ і т. д. Якщо слово, що починається з певної літери (цифри), єдине, то воно відразу записується в першому вузлі.
Приклад 1. Дано множину {А, АА, ABC, ABCD, АБСА, АВСС, BOR, С, ССС, CCCD, СССВ, СССА}. Від вихідної множини перейдемо до побудови бору. Вихідний алфавіт - {A, В, С, D}. BOR - єдине слово на букву В, і воно побуквенно не розбивається. Вузли бору є вектори, кожна компонента яких є або ключ, або посилання (можливо порожнє) - табл. 4.
Приклад пошуку по бору Вузол 1 - корінь, і першу букву слід шукати тут. Якщо першою виявилася, наприклад, буква B, то з таблиці видно, що йому відповідає слово BOR. Якщо ж перша буква А, то перший вузол передає управління до вузла 2, де аналогічним чином відшукується друга літера. Вузол 2 вказує, що другими буквами будуть (пропуск), А, В і т. д.
Приклад. Нехай задано множина слів: воск, сок, оса, сто, сев, век, ост, сотка. Побудуємо m-арное дерево для цього списку (рис. 13).
На основі аналізу цього дерева може бути побудована табл. Приклад пошуку по бору Слід зазначити, що при побудові бору порядок букв в першому стовпці таблиці може бути довільним. Зрозуміло, що для кожного конкретного порядку букв заповнення таблиці буде різним. Припустимо, для нашого прикладу в списку слів потрібно знайти слово «ост» . Слово починається на букву «о» . Дивимося перетин першого стовпця з рядком, позначеної буквою «о» . Там записане посилання (3); отже, звертаємося до третьої колонки бору. Друга літера слова «ост» - буква «с» . На перетині третього стовпця і рядка з буквою "с" записане посилання (6), яка відправляє нас на перегляд шостого стовпця бору. У цьому стовпці бачимо два слова: «ост» і «оса» . Але оскільки третьою буквою шуканого слова є буква «т» , то на рядку, позначеному цією літерою, знаходимо слово «ост» .
Пошук хешування
В основі пошуку лежить перехід вихідної множини до множини хеш-функцій h(k). Хеш -функція має наступний вигляд: h(k) = k mod m, де k - ключ; m - ціле число; mod - залишок від цілочисельного ділення.
Наприклад, нехай дано множина {9, 1, 4, 10, 8, 5}. Визначимо для нього хеш-функцію h(k) = k mod m. • Нехай m=1, тоді h(k) = {0, 0, 0, 0}. Множина хешфункцій складається з нулів. • Нехай m=20, тоді h(k) = {9, 1, 4, 10, 8, 5}. Множина хешфункцій повторює вихідну множину. • Нехай m дорівнює половині максимального ключа m=[Kmах/2], тоді m = [10/2] = 5; h(k) = {4, 1, 4, 0, 3, 0}. Хеш-функція вказує адресу, за якою слід відшукувати ключ. Для різних ключів хеш-функція може приймати однакові значення, така ситуація називається колізією. Таким чином, пошук хешування полягає в усуненні колізій методом ланцюжків (рис. 14).
Рис. 14. Усунення колізій методом ланцюжків
Приклад 1. Дано множину ключів {7, 13, 6, 3, 9, 4, 8, 5}. знайти ключ К = 27. Хеш-функція дорівнює h(k) = k mod m; m = [13/2] = 6 (так як 13 - максимальний ключ); h(k) = {1, 1, 0, 3, 3, 4, 2 , 5}. Для усунення колізій побудуємо табл. 6. Попарним порівнянням множини хеш-функцій і множини вихідних ключів заповнюємо таблицю. При цьому хеш-функція вказує адресу, за якою слід відшукувати ключ. Наприклад, якщо відшукується ключ К=27, тоді h(k) = 27 mod 6 = 3. Це означає, що ключ К=27 може перебувати тільки в рядку, де h(k) = 3. Так як його там немає, то даний ключ відсутній у вихідній множині.
Алгоритми пошуку словесної інформації
Алгоритм Кнута-Морріса-Пратта (КМП). Даний алгоритм отримує на вхід слово X = х [1]х[2]. . . х[n] і переглядає його зліва направо, буква за буквою, заповнюючи при цьому масив натуральних чисел l[1]. . . l[n], де l[i] - довжина слова l(х[1]. . . х[і]). Таким чином, l[i] є довжина найбільшого початку слова х[1]. . . x[n] одночасно є його закінченням.
Алгоритм Бойєр-Мура (БМ). Цей алгоритм робить те, що на перший погляд здається неможливим: в типовій ситуації він читає лише невелику частину всіх літер слова, в якому шукається заданий зразок. Нехай, наприклад, відшукується зразок abcd. Подивимося на четверту букву слова: якщо, приміром, це літера е, то немає ніякої необхідності читати перші три літери. (Справді, в зразку літери е нема, тому він може початися не раніше п'ятого літери. )
Алгоритм Рабіна. Цей алгоритм заснований на простій ідеї. Уявімо собі, що в слові довжиною m шукається зразок довжиною n. Виріжемо віконце розміром n і будемо рухати його по вхідному слову. При цьому перевіряємо, не співпадає слово у віконці з заданим зразком. Порівнювати по буквах довго. Натомість фіксуємо деяку функцію, визначену на словах довжиною n. Якщо значення цієї функції на слові в віконечку і на зразку різні, то збігу немає. Тільки
Виграш при такому підході полягає в наступному. Щоб обчислити значення функції на слові в віконечку, потрібно прочитати всі букви цього слова. Так вже краще їх відразу порівняти зі зразком. Проте виграш можливий, тому що при зсуві віконця слово не змінюється повністю, а лише додається буква в кінці і забирається на початку. Замінимо всі букви в слові і зразку їх номерами, котрі представляють собою цілі числа. Тоді зручною функцією є сума цифр. (При зсуві віконця потрібно додати нове число і відняти зникле. )
Питання?
Дякую за увагу!!!