Структура даних для наборів дерев.


10

Спроби дозволяють ефективно зберігати списки елементів. Префікси поділяються, щоб він був просторовим.

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

Зазвичай я б зберігав близько 500 незбалансованих бінарних дерев висотою менше 50.

EDIT

Моя програма - це якась перевірка моделі, яка використовує якусь пам ятку. Уявіть, що у мене є стан та такі формули: f = ϕ і g = ( ϕ ψ ), причому ϕ є складною підформулою, і уявіть, що я спершу хочу знати, чи f тримається в s . Я перевіряю, чи має місце ϕ, і після тривалого процесу я виявляю, що це так. Тепер я хочу знати, чи g тримається в s . Мені хотілося б пам’ятати той факт, що f тримається, і помітити, що g fsf=ϕг=(ϕψ)ϕfсϕгсfгfтак що я можу вивести в і майже враз. І навпаки, якщо я довів, що g не втримується в t , то я хочу сказати, що f майже не втримується в t .гс
гтfт

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

Наразі і l реалізуються як списки, і це явно не є оптимальним, оскільки мені потрібно повторити всі збережені формули окремо. Якби мої формули були послідовностями, і якщо частковий порядок був "префіксом", то трие може виявитись набагато швидше. На жаль, мої формули мають деревоподібну структуру на основі ¬ , , модального оператора та атомних пропозицій.Lл¬,

Як зазначають @Raphael та @Jack, я міг би послідовно ставити дерева, але я побоююся, що це не вирішить проблему, оскільки частковий порядок, який мене цікавить, не відповідав би "префіксу".


Просто швидка ідея: Ви спробували секвенціалізацію дерев (виконайте прохід по порядку, перерахуйте відвідані вузли відповідно і додайте спеціальні елементи для руху вгору, а потім зберігайте їх у трійці? Звичайно, це дозволило б "лише" перевірити ліві підкреслення, в певному сенсі.
Рафаель

2
Що робити, якщо ви просто використали серіалізацію дерев із наступною властивістю: T є піддією дерева T ', якщо і лише тоді, коли S ( T ) є підрядком S ( T ' ) ? Побудова такого S є простою (якщо ви вперше знайдете канонічну форму ваших дерев). Після цього ваше запитання еквівалентне збігу підрядків, що є широко вивченою проблемою в строгології. SТТ'S(Т)S(Т')S
Jukka Suomela

1
Погляньте на термін індексації .
starblue

1
Ще однією швидкою ідеєю було б зберігати всі дерева t1, t2, .. в одному великому дереві T, пам’ятаючи для кожного краю той набір дерев, до якого він входить. Тоді, щоб визначити, чи f є піддеревом одного із збережених дерев, спочатку визначаєте, чи f є піддеревом у T, і якщо так, то перетинаєте всі набори крайових міток цього піддерева. Відповідь - так, якщо перехрестя не порожнє. (Ви також можете поєднати два кроки).
Мартін Б.

Відповіді:


5

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

(Не лякайтеся, що зв'язаний документ стосується "мережевих мотивів у біологічних мережах": g-trie - це абсолютно гарна абстрактна структура даних для графіків.)


4

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


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

1
Оскільки я не був впевнений, що це за ваша програма, я запустив вашу аналогію на спроби, які зберігають рядки шляхом спільного використання префіксів. Однак ваш коментар про те, що "одне дерево може бути ключем до різних значень у різних словниках", схоже, також не підходить до спроб. Можливо, ви просто хочете отримати якусь колекцію підпису для дерева (та всіх його підрядів), на який ви можете подивитися? (наприклад, використання каталонських номерів для двійкових дерев або кодів Prufer для маркованих дерев.)
Jack

1

Це трохи схоже на ліс ( ліси, що розмежовуються ) ...

Він амортизує вартість вставки через техніку, яку називають об'єднанням за рангом, і пошукову операцію з використанням стиснення контуру . Я знаю, що існує також стійка версія цієї структури, розроблена Сільвеном Конхоном та Жаном-Крістофе Філіатре, але я не маю уявлення, чи це те саме, що згадує Джек ...



0

У «Чисто функціональних структурах даних» (1998) Кріс Окасакі пропонує спроби бінарних дерев, використовуючи агрегацію типів (10.3.2).

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


0

У програмі lingo: Якщо ви створюєте дерева з загальних підвиразів / дерев / DAG, ви матимете гарну компактну модель. Так спрямовані ациклічні графіки. Тоді б набору дерев вистачило.

Дерево громадського класу {Строкова операція; Дерево [] підкресли;

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 = новий HashMap ();

Отримати дерево (String izrazSyntax) {Дерево t = нове Дерево (); t.операція = ...; t.subtrees = ... рекурсивний виклик, щоб отримати підвищені вирази; Дерево t2 = commonSubExpressions.get (t); якщо (t2 == null) {t2 = t; commonSubExpressions.put (t2, t2); } повернути t2; }}

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