d-арна купа

Матеріал з testwiki
Версія від 01:36, 16 травня 2022, створена imported>Igor Yalovecky (Застосування)
(різн.) ← Попередня версія | Поточна версія (різн.) | Новіша версія → (різн.)
Перейти до навігації Перейти до пошуку

d-арна купа або d-купа це структура даних, що реалізує чергу з пріоритетом, узагальнення бінарної купи в якій вузли мають d дочірніх замість 2.[1][2][3] Отже, бінарна купа це 2-купа, а тернарна купа це 3-купа.

Ця структура даних дозволяє операції зменшення пріоритету виконуватись швидше ніж у бінарних купах за рахунок повільнішої операції видалення. Такий компроміс приводить до кращої швидкодії деяких алгоритмів, таких як алгоритм Дейкстри, в якому операції зменшення пріоритету відбуваються частіше ніж операції видалення найменшого елемента.[1][4] Додатково, d-арні купи краще взаємодіють з кешем процесора порівняно з бінарною купою, що дозволяє їм на практиці виконуватись швидше всупереч теоретично більшому часу виконання у найгіршому випадку.[5][6] Подібно до бінарних куп, d-арні купи не потребують додаткової пам'яті окрім пам'яті необхідної для збереження масиву елементів купи.[2][7]

Структура даних

d-арна купа складається з масиву з n елементів, кожен з яких має пов'язаний з ним пріоритет. Ці елементи можна розглядати як вузли у повному d-арному дереві, перелічені у порядку пошуку в ширину: елемент в позиції 0 утворює корінь дерева, елементи в позиціях 1-d — його діти, наступні d2 — онуки і т.д. Отже, батьківським елементом для елемента в позиції i (для будь-якого i>0) це елемент в позиції i1/d, а його дочірні елементи в позиціях з di+1 до di+d. Згідно з властивістю купи, в мін-купі, кожний елемент має пріоритет не менший ніж пріоритет батьківського елементу; в макс-купа, кожний елемент має пріоритет не більший ніж пріоритет батьківського елементу.[2][3]

Елемент з найменшим пріоритетом в мін-купі (або найбільшим в макс-купі) завжди можна знайти в позиції 0. Для видалення цього елемента, останній елементx в масиві пересувають на його місце і зменшують розмір масива на одиницю. тоді, допоки елемент x і його діти не задовольняють властивості купи, елемент x міняють місцями з одним з його дочірніх (тим, що має найменший пріоритет у мін-купі або тим, що має найбільший пріоритет в макс-купі), пересуваючи його донизу по дереву і в масиві, допоки, зрештою, властивість купи не виконано. Такий самий спадний обмін можна використати для збільшення пріоритету елемента в мін-купі або зменшення в макс-купі.[2][3]

Для додавання нового елемента до купи, елемент приєднують у кінець масиву, і міняють місцями з батьківським допоки властивість купи не дотримано. Таку саму висхідну процедуру обмінів можна використати для зменшення пріоритету елемента в мін-купі або збільшення в макс-купі.[2][3]

Для створення нової купи з масиву з n елементами, можна обійти елементи у зворотньому порядку, починаючи з останнього і закінчуючи елементом в позиції 0, застосовуючи спадний обмін для кожного елемента.[2][3]

Аналіз

У d-арній купі з n елементами, обидві процедури висхідного і спадного обміну можуть здійснити до logdn=logn/logd обмінів. У разі висхідного обміну, кожен обмін включає одне порівняння елемента з його батьком, і потребує сталого часу. Отже, час щоб вставити елемент до купи, зменшити пріоритет у мін-купі або збільшити в макс-купі є O(logn/logd). У процедурі спадного обміну, кожен обмін включає d порівнянь і потребує O(d) часу: необхідно виконати d1 порівнянь, щоб дізнатись максимум або мінімум серед дочірніх елементів і ще одне порівняння для визначення чи потрібен обмін. Звідси, видалення кореня дерева, збільшення пріоритету в мін-купі або зменшення в макс-купі займає O(dlogn/logd).[2][3]

При створенні d-арної купи з множини n елементів, більшість елементів початково перебувають у позиціях, які зрештою міститимуть листові елементи, і до них спадний обмін не застосовуватиметься. Щонайбільше n/d+1 елементів не є листовими і можуть бути переставлені не більше ніж один раз, за час O(d) необхідний на знаходження дочірнього елемента і обмін з ним. Не більше ніж n/d2+1 вузлів можуть бути обміняні двічі, потребуючи додатково O(d) часу для другого обміну на додачу до першого, який ми вже порахували, і т.д. Тому, у підсумку час для створення купи таким чином є

i=1logdn(ndi+1)O(d)=O(n).[2][3]

Точне значення формули (найбільшого можливого числа порівнянь під час створення d-арної купи) таке:

dd1(nsd(n))(d1(nmodd))(ed(nd)+1),[8]

де sd(n) це сума всіх чисел стандартного представлення числа n в d-базі і ed(n) це степінь d у факторизації n. Це зводиться до

2n2s2(n)e2(n), [8]

для d=2, і до

32(ns3(n))2e3(n)e3(n1),[8]

для d=3.

Використання пам'яті d-арною купою з операціями вставки і видалення є лінійним, бо вона не використовує додаткового місця окрім потрібного для розташування масиву, що містить елементи купи.[2][7] Якщо необхідно підтримувати зміну пріоритету елементів, що перебувають у купі, тоді користувач повинен також зберігати вказівники від елементів до їх позицій у купі, що знов-таки вимагає лінійної пам'яті.[2]

Застосування

Алгоритм Дейкстри для найкоротших шляхів у графах і алгоритм Прима для мінімальних кістякових дерев обидва використовують мін-купу з n операціями видалення найменшого елемента і m операціями зменшення пріоритету, де n це число вершин в графі і m це число ребер. Завдяки використанню d-арної купи з d=m/n, можна збалансувати підсумковий час цих двох операцій, що призведе до загального часу виконання алгоритму O(mlogm/nn), що буде поліпшенням порівняно з O(mlogn) у випадку бінарної купи коли кількість ребер значно більша ніж число вершин.[1][4] Альтернативна структура даних, що втілює чергу з пріоритетом — купа Фібоначчі, дає навіть кращий теоретичний час виконання, O(m+nlogn), але на практиці d-арні купи здебільшого щонайменше так само швидкі і часто навіть швидші ніж купи Фібоначчі в поєднанні з цими алгоритмами.[9]

На практиці, 4-купа може показувати кращі результати ніж бінарна купа, навіть для операцій з видалення найменшого елемента.[2][3] Додатково, d-арна купа швидша для розмірів купи, що перевищують розмір кеш пам'яті: Зазвичай, бінарна купа потребує більше хиб кешу і Шаблон:Нп віртуальної пам'яті ніж d-арна купа, кожна з яких вимагає набагато більше часу в порівнянні з роботою викликаною додатковими порівняннями, які виконує d-арна купа.[5][6]

Примітки

Шаблон:Reflist

Посилання