Существует ли структура данных для быстрой обработки списка и запросов заказа?

9

У нас есть набор, Lсписков элементов из множества N={1,2,3,...,n}, Каждый элемент изN появляется в одном списке в L, Я ищу структуру данных, которая может выполнять следующие обновления:

  1. concat(x,y) : объединяет список, содержащий y в конец списка, содержащего x

  2. split(x) : разбивает список, содержащий x сразу после x

Также необходимо выполнить следующие запросы:

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

  2. first(x) : возвращает первый элемент списка, содержащий x

  3. next(x) : возвращает следующий элемент после x в списке, содержащем x

Я уже придумал структуру данных, которая выполняет эти обновления в O(lg2(n)) и запросы в O(lg(n))время. Меня больше всего интересует, существует ли уже структура данных, которая может это сделать (надеюсь, быстрее?).

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

bbejot
источник

Ответы:

11

Держите ваши целые числа в списках пропуска. Обычные списки пропусков упорядочены по ключу, но мы просто будем использовать их как представление последовательностей. Кроме того, поддерживать массив указателей размераn, Каждый элемент массива должен указывать на узел в списке пропуска. Я считаю, что это поддерживаетnext в O(1) и все остальные операции в O(lgn),

В частности:

  • concatили splitTing два пропуска списков занимает O(lgn) время и, следовательно, делает недействительным самое большее O(lgn) указатели.
  • next просто следует за указателем вперед на уровне листа, принимая O(1) время.
  • first принимает O(lgn)время: следите за указателями, пока не застрянете, затем следуйте за левым указателем. Когда вы не можете больше следовать указателям слева, вы находитесь в заголовке списка пропуска. Следуйте указателям вниз до листа, затем один указатель вперед. Это первый элемент в списке.
  • followsнесколько сложнее. Действуйте как вfirst за y, но запишите список значений, где вы застряли (то есть, когда вы больше не можете следить за указателями). Мы назовем этот список записанным вами «следом». Сделать то же самое дляx, но следуйте указателям вправо, когда вы застряли, а не налево. Еслиx предшествует yИх следы будут пересекаться. Следы имеют размерO(lgn), Если каждый элемент в трассе помечен застрявшим уровнем, мы можем проверить пересечение во времениO(lgn),

next в худшем случае O(1)все остальные O(lgn) с большой вероятностью . Они могут быть сделаны в худшем случае, используя детерминированные списки пропусков.

Я думаю concat может быть изготовлен O(lglgn)используя (2,5) деревья на уровне листьев и усиливая шипы. Трюк с загрузкой см. В разделе « Чисто функциональные представления отсортированных списков, которые можно было сгенерировать ». Автор Kaplan и Tarjan.

jbapple
источник
прохладно. я думал о том, чтобы пропустить списки, но не мог понять, как это сделать без соответствующих значений ключа.
Сашо Николов
Это замечательно; Я вижу, как сделать все обновления детерминированнымиO(lg(n)), и это хорошо. Я должен продолжать читать, чтобы понять O (LG LG (N)). Спасибо за сообщение @jbapple.
bbejot
1

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

Шон Харкер
источник
спасибо за ссылку. Ближайшая проблема общих предков, безусловно, решает достижимость деревьев. Документ, на который вы ссылаетесь, описывает инкрементное дерево со всеми операциями вO(lglg(n))время. Интересно, можно ли его улучшить и с полностью динамическими деревьями?
bbejot