Чи є стабільна купа?


32

Чи існує структура даних пріоритетної черги, яка підтримує наступні операції?

  • Вставка (x, p) : додайте новий запис x з пріоритетом p
  • StableExtractMin () : Повернення та видалення запису з мінімальним пріоритетом, розрив зв'язків у порядку вставки .

Таким чином, після Insert (a, 1), Insert (b, 2), Insert (c, 1), Insert (d, 2) послідовність StableExtractMin повернеться a, то c, тоді b, d.

Очевидно, що можна використовувати будь-яку структуру даних черги пріоритету, зберігаючи пару як фактичний пріоритет, але мене цікавлять структури даних, які явно не зберігають час вставки (або порядок вставки) за аналогією до стабільного сортування.(p,time)

Еквівалентно (?): Чи існує стабільна версія сукупності, яка не потребує додаткового простору ?Ω(n)


Я думаю, ти маєш на увазі "а, тоді с, потім б, потім d"?
Росс Снайдер

Купа із пов’язаним списком записів + збалансоване бінарне дерево, введене на пріоритет, вказуючи на відповідний пов'язаний список, не працюватиме? Що я пропускаю?
Ар'ябхата

Морон: Це явно зберігає порядок вставки, саме цього я хочу уникати. Я уточнив постановку проблеми (і зафіксував помилку Росса).
Jeffε

Відповіді:


16

Метод Бенті-Сакса дає досить природну стійку чергу пріоритетів.

Зберігайте свої дані в послідовності відсортованих масивів . A i має розмір 2 i . Кожен масив також підтримує лічильник c i . Записи масиву A i [ c i ] , , A i [ 2 i - 1 ] містять дані.А0,,АкАi2iciАi[ci],,Аi[2i-1]

Для кожного , все елементи А я були додані пізніше , ніж в А я + 1 , і в межах кожного A I елементи впорядковані за значенням зі зв'язками порушуються шляхом розміщення старих елементів попереду нових елементів. Зауважте, що це означає, що ми можемо об'єднати A i і A i + 1 і зберегти це впорядкування. (У випадку зв’язків під час злиття візьміть елемент з A i + 1. )iАiАi+1АiАiАi+1Аi+1

Щоб вставити значення , знайдіть найменше i таке, що A i містить 0 елементів, об'єднайте A 0 , , A i - 1 і x , збережіть це в A i і встановіть c 0 , , c i відповідним чином.хiАiА0,,Аi-1хАic0,,ci

Для витягування min знайдіть найбільший індекс такий, що перший елемент в A i [ c i ] мінімальний за всі i i з приростом c i .iАi[ci]ici

За стандартним аргументу, це дає амортизується час на операцію і стабільно з - за впорядкування описано вище.О(журналн)

Для послідовності з вставок та вилучень для цього використовується n записів масиву (не зберігайте порожні масиви) плюс O ( log n ) слів даних бухгалтерії. Це не відповідає версії питання Міхай, але показує, що стійке обмеження не потребує великих витрат на приміщення. Зокрема, це свідчить про відсутність нижньої межі Ω ( n ) на необхідному додатковому просторі.ннО(журналн)Ω(н)

Оновлення: Рольф Фагерберг вказує, що якщо ми можемо зберігати нульові (не дані) значення, то всю цю структуру даних можна упакувати в масив розміром , де n - кількість вставок на даний момент.нн

По-перше, зауважте, що ми можемо запакувати у масив у такому порядку ( спочатку A k , а потім A k - 1, якщо він не порожній тощо). Структура цього повністю закодована двійковим поданням n , кількістю елементів, вставлених дотепер. Якщо бінарне подання n має 1 у положенні i , то A i буде займати розташування масиву 2 i , інакше воно не займе жодного місця розташування масиву.Ак,,А0АкАк-1ннiАi2i

Під час вставки, та довжини нашого масиву збільшуємо на 1, і ми можемо об'єднати A 0 , , A i плюс новий елемент, використовуючи існуючі на місці стабільні алгоритми злиття.нА0,,Аi

Тепер, де ми використовуємо нульові значення, це позбавлення від лічильників . У A i ми зберігаємо перше значення, за ним - значення c i null, а потім - 2 i - c i - 1 . Під час витягу-хв ми все ще можемо знайти значення для вилучення за час O ( log n ) , дослідивши A 0 [ 0 ] , , A k [ 0 ] . Коли ми знайдемо це значення в A i [ 0ciАici2i-ci-1О(журналн)А0[0],,Ак[0] ми встановлюємо A i [ 0 ] на null, а потім робимо двійковий пошук на A i, щоб знайти перше ненулеве значення A i [ c i ] і підміняти A i [ 0 ] і A i [ c i ] .Аi[0]Аi[0]АiАi[ci]Аi[0]Ai[ci]

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


1
Тут потенційно використовується O (n) додатковий простір в даний момент після O (n) вилучення, ні? У цей момент ви також можете зберігати пріоритет ...
Мехрдад

10

Я не впевнений, які ваші обмеження; чи відповідає наступне? Зберігайте дані в масиві, який ми інтерпретуємо як неявне бінарне дерево (як бінарне коло), але з елементами даних на нижньому рівні дерева, а не у його внутрішніх вузлах. Кожен внутрішній вузол дерева зберігає менші значення, скопійовані з двох його дітей; у разі зв’язків скопіюйте ліву дитину.

Щоб знайти мінімум, подивіться на корінь дерева.

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

Щоб вставити елемент, додайте його до наступного вільного положення в нижньому рядку дерева та оновіть шлях до кореня. Або, якщо нижній рядок стає заповненим, подвоюйте розмір дерева (знову ж таки аргументом амортизації; зауважте, що ця частина нічим не відрізняється від необхідності перебудови, коли стандартна двійкова купа переростає її масив).

Це не є відповіддю на більш сувору версію питання Михайла, оскільки вона використовує вдвічі більше пам’яті, ніж повинна бути справжня неявна структура даних, навіть якщо ми ігноруємо космічну вартість обробки видалень.


Мені подобається це. Так само, як і при звичайному неявному дереві min-heap, ймовірно, 3-арне або 4-арнове неявне дерево буде швидше через ефекти кешу (хоча вам потрібно більше порівнянь).
Джонатан Гріл

8

Чи є наступним правильне тлумачення вашої проблеми:

Ви повинні зберігати N клавіш у масиві A [1..N] без допоміжної інформації, щоб ви могли підтримувати: * клавіша вставки * delete min, яка вибирає найраніший вставлений елемент, якщо є кілька мінімумів

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

Цікаво.


1
Я думаю, що це має бути коментар, а не відповідь, оскільки це насправді не відповідає початковому запитанню. (Ви можете видалити його та додати як коментар.)
Jukka Suomela

5
Так, цей веб-сайт трохи смішний. У нас є репутація, бонуси, нагороди, всілякі способи коментувати, що я не можу з’ясувати. Я б хотів, щоб це виглядало менш як дитяча гра.
Михай

1
Я думаю, що йому потрібно більше представників, щоб розмістити коментар. ось у чому проблема.
Суреш Венкат

@ Суреш: О, так, я цього не пам’ятав. Як ми насправді повинні вирішувати подібну ситуацію (тобто новому користувачеві потрібно запитати роз'яснення, перш ніж відповісти на запитання)?
Jukka Suomela

2
Немає легких шляхів. Я часто бачив це в МО. Міхай не матиме проблем із здобуттям представника, якщо його Mihai я думаю, що це :)
Suresh Venkat

4

Коротка відповідь: Ви не можете.

Трохи довша відповідь:

Вам знадобиться додатковий простір, щоб зберігати "вік" вашої записи, що дозволить вам розрізняти однакові пріоритети. І вам знадобиться простір Ω ( n ) для інформації, яка дозволить швидко вставляти та витягувати. Плюс ваше корисне навантаження (значення та пріоритет).Ω(n)Ω(н)

І за кожне збережене вами корисне навантаження ви зможете "заховати" деяку інформацію в адресу (наприклад, означає, що Y старше X). Але в цій "прихованій" інформації ви або приховатимете "вік", або "швидкий пошук" інформації. Не обоє.аггr(Х)<аггr(Y)


Дуже довга відповідь неточною лускатою псевдо-математикою:

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

Давайте подумаємо про кількість даних, що беруть участь у X-бітовій машині (скажімо, 32 або 64-бітної), із записами (значення та пріоритет) машинними словами.П

У вас є набір потенційних записів, який частково впорядкований: та ( a , 1 ) = ( a , 1 ), але ви не можете порівняти ( a , 1 ) та ( b , 1 ) .(а,1)<(а,2)(а,1)=(а,1)(а,1)(б,1)

Однак ви хочете мати можливість порівняти два непорівнянні значення зі свого набору записів, залежно від того, коли вони були вставлені. Так що у вас є тут ще один набір значень: ті , які були вставлені, і ви хочете підвищити його за допомогою часткового порядку: тоді і тільки тоді X був вставлений перед Y .Х<YХY

У гіршому випадку ваша пам’ять заповниться записами форми ? Різними для кожного), тому вам доведеться повністю покладатися на час вставки, щоб вирішити, який з них буде перший.(?,1)?

  • Час вставки (по відношенню до інших записів, що все ще в структурі) вимагає бітів інформації (з корисним навантаженням P-байтів та 2 X доступними байтами пам'яті).Х-лог2(П)2Х
  • Корисне навантаження (значення та пріоритет вашого запису) вимагає машинних слів інформації.П

Це означає, що ви повинні якось зберігати додаткові біти інформації для кожної записи, яку ви зберігаєте. І це O ( n ) для n записів.Х-лог2(П)О(н)н

Тепер, скільки бітів інформації нам надає кожна "комірка" пам'яті?

  • біт даних ( W - ширина машинного слова).WW
  • біт адреси.Х

Тепер припустимо (корисна навантаження становить щонайменше одне машинне слово в ширину (зазвичай один октет)). Це означає, що X - l o g 2 ( P ) < X , тому ми можемо помістити інформацію про порядок вставки в адресу комірки. Ось що відбувається в стеку: клітинки з найнижчою адресою увійшли в стек першими (і вийдуть останніми).П1Xlоg2(П)<Х

Отже, для зберігання всієї нашої інформації у нас є дві можливості:

  • Зберігайте порядок вставки за адресою та корисне навантаження в пам'яті.
  • Зберігайте обидва в пам’яті та залиште адресу вільною для іншого використання.

Очевидно, щоб уникнути відходів, ми використаємо перше рішення.


Тепер про операції. Я думаю, ви хочете мати:

  • з O ( l o g n ) часовою складністю.Янсеrт(таск,priоriту)О(логн)
  • з O ( l o g n ) часовою складністю.SтаблеЕхтrаcтМiн()О(логн)

Давайте подивимось на :SтаблеЕхтrаcтМiн()

Дійсно загальний алгоритм виглядає так:

  1. О(логн)
  2. О(логн)
  3. Поверніть його.

0(1)О(1)О(1)

О(логн)2(Х-лог2(П))

Х-лог2(П)О(логн)О(логн)

О(логн)

О(логн)Х-лог2(П)

О(логн)

Х-лог2(П)О(логн)

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


Х-лог2(П)

  • Х-лог2(П)
  • П
  • Х-лог2(П)

Ω(н)


чи справді ви мали намір дати відповідь CW?
Суреш Венкат

Так. Моя відповідь не на 100% правильна, як сказано в ній, і було б добре, якщо хтось міг би її виправити, навіть якщо я більше не перебуваю на ТАК чи що завгодно. Знання повинні ділитися, знання повинні бути змінними. Але, можливо, я неправильно зрозумів використання CW, якщо так, скажіть будь ласка :). EDIT: так, я дійсно щойно виявив, що я не отримаю жодної репутації від публікацій CW і що вміст дозволено CC-wiki будь-яким чином ліцензованим ... Шкода :).
Сюзанна Дуперон

3

Якщо ви реалізуєте свою чергу пріоритетів як збалансоване бінарне дерево (популярний вибір), тоді вам просто потрібно переконатися, що коли ви додаєте елемент до дерева, він вставляється зліва від будь-яких елементів з рівним пріоритетом.
Таким чином, порядок вставки кодується в структурі самого дерева.


1
Але це додає O (n) місця для покажчиків, що, на мою думку, те, що запитуючий хоче уникати?
Джеремі

-1

Я не думаю, що це можливо

конкретний випадок:

       x
    x    x
  x  x  1  x
1  x  

хв. хв з усіма х> 1

загострення зрештою дасть щось подібне на вибір

       x
    1    1
  x  x  x  x
x  x  

тепер, який 1 поширити на корінь?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.