Чи існує структура даних для швидкого маніпулювання списком та замовлення запитів?


9

У нас є набір, , списків елементів із множини . Кожен елемент з з'являється в одному списку в . Я шукаю структуру даних, яка може виконувати такі оновлення:LN={1,2,3,...,n}NL

  1. concat(x,y) : об'єднує список, що містить на кінець списку, що міститьyx

  2. split(x) : розбиває список, що містить безпосередньо післяxx

Він також повинен виконувати такі запити:

  1. follows(x,y) : повертає якщо і знаходяться в одному списку, а поступає після (але не обов'язково примикає до )truexyyxx

  2. first(x) : повертає перший елемент списку, що міститьx

  3. next(x) : повертає наступний елемент після у списку, що міститьxx

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

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

Відповіді:


11

Зберігайте цілі числа у пропущених списках. Нормальні списки пропуску впорядковані за ключем, але ми просто використовуватимемо їх як подання послідовностей. Додатково підтримуйте масив покажчиків розміром . Кожен елемент масиву повинен вказувати на вузол у списку пропусків. Я вважаю, що це підтримує в та всі інші операції в .nnextO(1)O(lgn)

Конкретно:

  • concat або двох пропускних списків займає час тому недійсне для більшості покажчиків.splitO(lgn)O(lgn)
  • next просто слід вказівник вперед на рівні аркуша, приймаючи час .O(1)
  • first займає час : слідкуйте за покажчиками, поки ви не застрягнете, а потім слідуйте за лівою вказівкою. Якщо ви не можете слідувати більше лівих покажчиків, ви знаходитесь біля головного вказівника вашого списку пропусків. Виконайте вниз покажчики до аркуша, потім один вказівник вперед. Це перший елемент у списку.O(lgn)
  • follows дещо складніше. Поступайте як у для , але запишіть список значень, де ви застрягли (тобто там, де ви більше не можете переглядати покажчики). Ми назвемо цей список, який ви записуєте, "слід". Зробіть те ж саме для , але слідуйте праворуч, коли ви застрягли, а не ліворуч. Якщо передує , їх сліди будуть перетинатися. Сліди мають розмір . Якщо кожен елемент у сліді зазначається із застряглим рівнем, ми можемо перевірити перетин у часі .firstyxxyO(lgn)O(lgn)

next - найгірший , всі інші - з великою часткою ймовірності . Їх можна зробити в гіршому випадку, використовуючи детерміновані пропускні списки.O(1)O(lgn)

Я думаю, що можна зробити , використовуючи дерева (2,5), пов’язані з листям, і підсилюючи колючки. Для підказки завантаження дивіться " Чисто функціональні подання відсортованих списків, що підлягають каналу " Каплана та Тарджана.concatO(lglgn)


круто. Я думав про пропуск списків, але не міг зрозуміти, як це зробити, не пов'язані з ключовими значеннями.
Сашо Ніколов

Це чудово; Я бачу, як зробити усі оновлення детермінованимиO(lg(n)), що добре. Мені доведеться читати, щоб зрозуміти O (lg lg (n)). Дякуємо за повідомлення @jbapple.
bbejot

1

Найменший загальний предок проблема може бути використаний для вирішення проблеми досяжності в динамічних кореневих дерев, так що я вважаю , ви будете також можуть зацікавити наступні: Оптимальні алгоритми пошуку найближчого загального Предків в динамічних дерев , по Alstrup і Thorup. Цей документ дає обмежений часO(n+mloglogn) для n посилання та m nca запитів на вказівній машині.


дякую за довідку. Найближча загальна проблема предків, безумовно, вирішує доступність дерев. У документі, до якого ви посилаєтесь, описується додаткове дерево з усіма операціями вO(lglg(n))час. Цікаво, чи можна вдосконалити роботу і з повністю динамічними деревами.
bbejot
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.