Чи існує черговість черги з витягами ?


46

Існує дуже багато структур даних, які реалізують інтерфейс черги з пріоритетом:

  • Вставка: вставити елемент в структуру
  • Get-Min: повертає найменший елемент у структурі
  • Extract-Min: видаліть найменший елемент структури

Поширеними структурами даних, що реалізують цей інтерфейс, є (хв) купи .

Зазвичай (амортизовані) тривалість цих операцій:

  • Вставте: (іноді )O ( журнал n )O(1)O(logn)
  • Get-Min:O(1)
  • Extract-Min:O(logn)

Купи Фібоначчі досягають ці запущені рази, наприклад. Тепер моє запитання таке:

Чи існує структура даних із наступним (амортизованим) періодом роботи?

  • Вставити:O(logn)
  • Get-Min:O(1)
  • Extract-Min:O(1)

Якщо ми можемо побудувати таку структуру за час, заданий відсортованим входом, тоді ми можемо, наприклад, знайти перетини ліній на попередньо відсортованих входах з перехрестя строго швидше, ніж якщо ми використовуємо "звичайні" черги пріоритету.о ( нO(n)o(nlogn)


Я думаю, якщо використовувати збалансований BST, це не врівноважиться при виконанні Extract-Min. А може пропустити список.
svick

@svick: пропускні списки рандомізовані, що я не шукаю. Якщо ви можете зробити це з BST, то це здорово, але я думаю , що ви повинні зробити якийсь - то вид балансування.
Олексій десять Бринк

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

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

Відповіді:


27

Наша ідея полягає у використанні різьбових ігрових дерев . Окрім статті у Вікіпедії, ми будемо обробляти нитки дерев, щоб кожен вузол мав вказівник nextна свого наступника в обході порядку; ми також тримаємо вказівник startна найменший елемент дерева.

Неважко помітити, що витяг найменшого елемента можливий за (найгірший) час : просто слідуйте за вказівником, видаліть мінімум та змініть вказівник на мінімальний . Мінімум ніколи не може мати ліву дитину; якщо у нього є правильна дитина, ми ставимо її на мінімальне місце на дереві. Ми не виконуємо операцію splay, яку зазвичай роблять splay дерева. Результатом є дерево пошуку, яке все ще є достатньо збалансованим: оскільки ми видаляємо лише вузли на лівому фланзі, ми знаємо, що коли кількість вузлів (у підвладному періоді) впливає на половину від початкового числа через видалення, ) висота дерева зменшується на одиницю.O(1)startnext

Вставки можливі через амортизований час ; Зигзагоподібні (а що ні) операції також будуть добре балансувати дерево.O(logn)

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


2
Мені незрозуміло, як змусити амортизований аналіз працювати, якщо ви не переслідуєте на ExtraMin. Чи можете ви дати підказку?
jbapple

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

9
Обережно! Сиві дерева не обов’язково врівноважуються. Вузли, до яких тривалий час немає доступу, можуть бути дуже глибокими в дереві. Для того, щоб аналіз пройшов аналіз, вам доведеться сперечатися з точки зору тієї ж потенційної функції, яка використовується для аналізу знаків.
JeffE

20
  • Вставити:O(logn)
  • Get-Min:O(1)
  • Extract-Min:O(1)

Амортизований час

Прості реалізації черги пріоритетів (наприклад, будь-яка збалансована BST або стандартна бінарна min-купа) можуть досягти цих (амортизованих) термінів роботи, просто стягуючи витрати на Extract-Min для вставки та підтримуючи вказівник на мінімальний елемент. Наприклад, у вас може бути потенційна функція, яка є . Потім вставлення нового елемента збільшує потенціал на , і тому амортизована вартість вставки все ще , але Extract-Min () зменшує потенціал на , і тому амортизована вартість становить лише .O ( log n ) O ( log n ) Ω ( log n ) O ( 1 )cnlognO(logn)O(logn)Ω(logn)O(1)

Найгірший випадок

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


1
Як дуже підлий. Ви маєте рацію, я думаю, я мав би вимагати чогось більш сильного, щоб це виключити. Хороша ідея :)
Алекс десять Бринк

@AlextenBrink Ви можете вимагати видалення найгіршому випадку . (що, здається, для чого йшло деякі інші відповіді), я додав абзац до своєї відповіді, щоб вирішити цю справу. O(1)
Джо

14

2-4 дерева мають амортизовані модифікації у відомих місцях. Тобто, якщо у вас є вказівник на якесь місце на дереві, ви можете вилучити або додати елемент там за амортизований час .O ( 1 )O(1)O(1)

Таким чином, ви можете просто тримати вказівник на мінімальний елемент та кореневий вузол у дереві 2-4. Вставки повинні пройти через кореневий вузол. Оновлення покажчика до мінімуму є тривіальним після deleteMin, а deleteMins - час (амортизований).O(1)

Цікава сторона: червоно-чорні дерева - це лише спосіб перегляду 2-4 дерев. Дизайнери стандартних реалізаторів бібліотеки C ++ 98 поставляють контейнер на основі червоного-чорного дерева, і стандарт визначає, що введення та видалення повинно бути амортизованим часом у відомих місцях (які вони називають "ітераторами" ). Однак насправді це набагато складніше для червоно-чорних дерев, ніж для 2-4 дерев, оскільки для цього потрібні ліниві розмітки вузлів, які потрібно перефарбувати. Наскільки мені відомо, жодна реалізація стандартної бібліотеки C ++ 98 не відповідала цій особливій вимозі.O(1)


8

За запитом, ось структура, яку я знайшов після того, як сформулював питання:

Основна ідея полягає у використанні різьбового дерева Scapegoat разом із вказівником до мінімуму (і на користь, максимуму також). Більш простою альтернативою нитковій роботі є підтримка попередніх та наступних вказівників у кожному вузлі (що еквівалентно, простіше, але має більше накладних витрат). Я прийшов назвати це купами Scapegoat , просто щоб дати йому якусь назву.

Саме ця основна структура дає вам такі операції:

  • Пошук: надавши ключ, повертає вказівник на відповідний вузол у час.O(logn)
  • Вставка: наданий ключ, вставляє ключ у структуру, повертаючи покажчик на цей вузол у час.O(logn)
  • Попередник / наступник: заданий покажчик повертає наступника чи попередника в час.O(1)
  • Get-Min / Max: повертає вказівник до мінімуму чи максимуму.

При аналізі дерев Scapegoat балансуючий накладний вилучення аналізується як , але аналіз фактично дає баланс накладних витрат (який ігнорується в роботі оскільки вони також рахують час, необхідний для пошуку вузла, який потрібно видалити). Отже, якщо у нас є вказівник на вузол, ми можемо видалити його за постійний час (це можна зробити в дереві двійкового пошуку з потоком в час) і поєднати з накладні балансування, це дає час видалити:O ( 1 ) O ( log n ) O ( 1 ) O ( 1 ) O ( 1 )O(logn)O(1)O(logn)O(1)O(1)O(1)

  • Видалити: задавши вказівник, видаляє вузол у час.O(1)

Поєднавши це:

  • Extract-Min / Max: видаляє мінімальний / максимальний вузол за час.O(1)

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

Ще деякі речі:

  • Побудова: задано клавіш у відсортованому порядку, побудуйте купу Scapegoat в час.O ( n )nO(n)
  • Баланс: врівноважте дерево, таким чином воно формує ідеально збалансоване дерево бінарного пошуку (зменшує накладні результати пошуку) за час (ви можете зробити це постійним коефіцієнтом швидше, ніж папір пропонує, до речі, використовуючи покажчики попередника / наступника).O(n)

І нарешті, я впевнений, що ви можете підтримати ці операції, але мені потрібно трохи подумати над цим, перш ніж знати це точно:

  • Insert-New-Min / Max: наданий ключ, менший / більший, ніж будь-який ключ, який уже є в структурі, вставляє ключ у структуру, повертаючи вказівник на цей вузол у час.O(1)

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

O(lgn)O(1)O(lgn)

2
O(1)O(1)O(1)O(1)
Олексій десять Брінк

Ах, я зараз розумію.
jbapple

2

ϵO(1)log(1/ϵ)ϵ

ϵn

Про оригінальний, чіткий і красиво написаний документ див. Бернард Шазел, «М’яка купа»: приблизна черговість пріоритету з оптимальним коефіцієнтом помилок, Журнал ОСББ, 47 (6), стор. 1012-1027, 2000 . Про альтернативну реалізацію та аналіз, що вважає простішими та інтуїтивнішими від SODA'09, див. Kaplan H. & Zwick U., Простіша реалізація та аналіз м'яких купи Chazelle, 2009 .


Хоча дуже цікава структура даних, м'які купи не є точними: findmin може повернути значення, яке не є мінімальним, а є лише приблизним мінімумом. Дякую за посилання все одно :)
Alex ten Brink

1
@AlextenBrink: суть структури даних (як і багато ймовірнісних алгоритмів) полягає в тому, що ви можете використовувати приблизну структуру даних для отримання точних відповідей. Насправді приблизна природа м'яких купи не заважала використовувати її в єдиному відомому алгоритмі лінійного часу для дерева з мінімальним розміщенням.
Jérémie

2

Гаразд, нарешті, ви отримали складність, яку ви шукали, і що найкраще, я знайшов це в літературі:

Найгірша складність

O(1)

O(1)

O(1)

O(log n)

Довідково

[3]O(1)O(log n)O(n)

Бродал, Герт Штолтінг. "Черги з швидким розплавленням". У працях 4-го Міжнародного семінару з алгоритмів та структур даних, 282–290. WADS '95. Лондон, Великобританія, Великобританія: Спрингер-Верлаг, 1995.

[3]: Дієц, Павло Ф і Радєєв Раман. "Дерево пошуку постійного пальця часу". Листи з обробки інформації 52, вип. 3 (1994): 147 - 154.

Хоча для цього використовується модель обчислення ОЗУ :

У нашій структурі даних використовується модель машини з випадковим доступом (ОЗУ) з мірою одиниці витрат та розміром логарифмічного слова;

Зовсім недавно була представлена модель обчислювального рішення Pointer-Machine[1] .

[1]: Бродал, Герт Столтінг, Джордж Лагогіаніс, Христос Макрис, Атанасіос Цакалідіс, Костас Циклас. "Оптимальні пальчикові дерева пошуку в машині вказівника". J. Comput. Сист. Наук. 67, ні. 2 (вересень 2003 р.): 381–418.


2

Підхід до цієї проблеми, підтримуючи дві структури даних: масив та бінарне дерево.

Ω(lognloglogn)Ω(logn)

O(logn)O(logn)

nullO(logn)

O(1)O(1)

O(logn)O(1)delete_at(idx)


1 Патраску, Міхай та Ерік Д. Демен. «Логарифмічні нижні межі в моделі клітинного зонда». SIAM J. Comput. 35, ні. 4 (квітень 2006 р.): 932–963. doi: 10.1137 / S0097539705447256.


1
O(logn)

Що означає "потік бінарного дерева пошуку в масив"?
jbapple

@AT: Я поділяю настрої jbapple.
Рафаель

Ω(k)kO(1)

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

-2

O(1)O(log log n)

Дивіться статтю 2007 року: Еквівалентність між пріоритетними чергами та сортуванням за Mikkel Thorup.

O(n log log n)


Хоча папір, з якою ви зв’язувались, цікава, черга пріоритетів, яку вони представляють, не має постійних видалень часу (якщо я читаю конспект правильно), а значить, я не прошу про це.
Олексій десять Бринк

-2

Аналіз

o(n log log n)

o(log log n)

O(1)

O(n)

O(1)

O(1)

Впровадження

  1. O(1)
  2. O(6)O(1)
  3. k±
    ((k>nsize1)(k<n0)((k<ni)(k>ni+1)))
    o(log log n)

[1]: Андерссон, Арн та Крістер Матссон. 'Динамічний інтерполяційний пошук в O (журнал журналу n) Час'. В «Автомати, мови та програмування» під редакцією Анджея Лінгаса, Рольфа Карлссона та Сванте Карлссона, 700: 15–27. Конспекти лекцій з інформатики. Спрингер Берлін / Гейдельберг, 1993. http://dx.doi.org/10.1007/3-540-56939-1_58 .


2
Ну, час вставки - це далеко від позначки.
Рафаель

nsize1n0nini+1

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

O(log n)

@AT Логарифмічний двійковий пошук потребує випадкового доступу. Як реалізується базовий список? Ви дійсно повинні сперечатися за заявлені межі. Також "позиції у списку" розпливчасті - на які позиції та на які символи посилаються? Не кожен має доступ до зв'язаного вами паперу. Будь ласка, спробуйте зробити свою відповідь (більше) самодостатньою і хоча б узагальнити факти. На даний момент я не вірю, що ваша відповідь правильна.
Джухо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.