Структура данных для множеств деревьев.

10

Попытки позволяют эффективно хранить списки элементов. Префиксы являются общими, что позволяет экономить место.

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

Обычно я храню около 500 несбалансированных бинарных деревьев высотой менее 50.

РЕДАКТИРОВАТЬ

Мое приложение - это своего рода средство проверки моделей, использующее какие-то памятки. Представьте, что у меня есть состояние и следующие формулы: и где является сложной подформулой, и представьте, что я сначала хочу узнать, выполняется ли в . Я проверяю, выполняется ли и после длительного процесса я понимаю, что это так. Теперь я хочу знать, содержит ли в . Я хотел бы вспомнить тот факт, что имеет место, и заметить, что так что я могу получить в почти мгновенно.f = ϕ g = ( ϕ ψ ) ϕ f s ϕ g s f g f g ssf=φg=(ϕψ)φеsφгsегегs
И наоборот, если я докажу, что не выполняется в , то я хочу сказать, что не сохраняется в почти мгновенно.т ф тгTеT

Мы можем построить частичный порядок на формулах и иметь если . Для каждого состояния мы храним два набора формул; хранит максимальные формулы, которые сохраняются, а хранит минимальные формулы, которые не сохраняются. Теперь, учитывая состояние и формулу , я могу видеть, ли , или если в этом случае я сделано, и я знаю непосредственно, держит ли в .g f s L ( s ) l ( s ) s g f L ( s ) , f g f l ( s ) , g f g sгегеsL(s)L(s)sгеL(s),егеL(s),гегs

В настоящее время и реализованы в виде списков, и это явно не оптимально, потому что мне нужно перебирать все сохраненные формулы по отдельности. Если бы мои формулы были последовательностями, и если частичный порядок был «является префиксом», то процесс может оказаться гораздо быстрее. К сожалению, мои формулы имеют древовидную структуру, основанную на , модальном операторе и атомарных предложениях.л ¬ , LL¬,

Как указывают @Raphael и @Jack, я мог бы упорядочить деревья, но боюсь, что это не решит проблему, потому что интересующий меня частичный порядок не будет соответствовать «является префиксом».

Абдаллах
источник
Просто быстрая идея: пробовали ли вы секвенировать деревья (выполнить обход по порядку, соответствующим образом перечислить посещенные узлы и добавить специальные элементы для перемещения вверх или вниз) и сохранить их в дереве? Конечно, в некотором смысле это «разрешит» только проверку левых поддеревьев.
Рафаэль
2
Что если вы просто использовали сериализацию деревьев со следующим свойством: T является поддеревом T тогда и только тогда, когда S ( T ) является подстрокой S ( T ) ? Построить такой S просто (если вы сначала найдете каноническую форму ваших деревьев). После этого ваш вопрос эквивалентен сопоставлению подстрок, что является широко изученной проблемой в области струнологии. STT'S(T)S(T')S
Юкка Суомела
1
Посмотрите на индексирование терминов .
звездный синий
1
Другая быстрая идея - хранить все деревья t1, t2, .. в одном большом дереве T, запоминая для каждого ребра множество деревьев, частью которых оно является. Затем, чтобы определить, является ли f поддеревом одного из сохраненных деревьев, вы сначала определяете, является ли f поддеревом в T, и если да, то пересекаете все наборы меток ребер этого поддерева. Ответ - да, если пересечение не пусто. (Вы также можете объединить два шага).
Мартин Б.

Ответы:

5

Возможно, вы захотите проверить G-попытки . По сути, это структура данных, которую вы ищете, но она предназначена для использования с общими графиками, а не просто с деревьями. Таким образом, я не уверен, что у g-try есть хорошие теоретические гарантии - я думаю, что они используют алгоритм канонизации графа в качестве подпрограммы - но на практике они, кажется, работают хорошо.

(Не пугайтесь, что связанная статья о «сетевых мотивах в биологических сетях»: g-trie - это очень хорошая абстрактная структура данных для графов.)

Джошуа Грохов
источник
4

Особой формой этого является постоянство : см. Статьи «Устойчивость структур данных Дрисколла, Сарнака, Слеатора и Тарьяна» и «Расположение плоской точки» с использованием деревьев постоянного поиска »Сарнака и Тарьяна, в которых хранятся семейства связанных деревьев.

Джек
источник
1
Спасибо за ссылки. В настоящий момент я не могу получить доступ к постоянным структурам данных , но я немного знаком с концепцией постоянства. Тем не менее, я не понимаю, как я могу использовать настойчивость для решения моей проблемы. Я действительно хочу использовать словари, которые отображают деревья на логические значения, и одно и то же дерево может быть ключом к различным значениям в разных словарях.
Абдалла
1
Поскольку я не был уверен в том, что было вашим приложением, я запустил вашу аналогию с попытками, которые хранят строки с помощью совместного использования префиксов. Однако ваш комментарий о том, что «одно и то же дерево может быть ключом к разным значениям в разных словарях», похоже, тоже не подходит для попыток. Возможно, вы просто хотите получить некоторую коллекцию подписей для дерева (и всех его поддеревьев), которые вы можете найти? (например, используя каталонские числа для двоичных деревьев или коды Пруфера для помеченных деревьев.)
Джек,
1

Это звучит немного как лес ( непересекающиеся леса ) ...

Он амортизирует стоимость вставки с помощью метода, называемого объединением по рангу, и операции поиска с использованием сжатия пути . Я знаю, что есть постоянная версия этой структуры, разработанная Сильвен Кончон и Жаном-Кристофом Филлиатром, но я понятия не имею, совпадает ли это с той, о которой упоминает Джек ...

Рено Линдек
источник
0

В «Чисто функциональных структурах данных» (1998) Крис Окасаки предлагает попытки двоичных деревьев с использованием агрегации типов (10.3.2).

Я не знаю, помогает ли это немедленно; данное решение может быть неосуществимо напрямую.

Рафаэль
источник
0

На языке программирования: если вы создаете деревья из общих подвыражений / trees / DAG, у вас будет хорошая компактная модель. Направленные ациклические графы. Тогда достаточно деревьев.

открытый класс Tree {String operation; Дерево [] поддеревья;

public int compareTo(Tree rhs) {
    if (rhs == null) return false;
    int cmp = operation.compareTo(rhs.operation);
    if (cmp == 0) {
        cmp = Arrays.compareTo(subtrees, rhs.subtrees);
    }
    return cmp;
}

...}

Карта commonSubExpressions = new HashMap ();

Tree get (String expressionSyntax) {Tree t = new Tree (); t.operation = ...; t.subtrees = ... рекурсивный вызов для получения подвыражений; Tree t2 = commonSubExpressions.get (t); if (t2 == null) {t2 = t; commonSubExpressions.put (t2, t2); } возврат t2; }}

Joop Eggen
источник