Struktura danych dla zbiorów drzew.

10

Próby pozwalają na efektywne przechowywanie list elementów. Prefiksy są wspólne, więc zajmuje mało miejsca.

Szukam podobnego sposobu skutecznego przechowywania drzew. Chciałbym móc sprawdzać członkostwo i dodawać elementy, wiedząc, czy dane drzewo jest poddrzewem niektórych przechowywanych drzew, czy też istnieje drzewo przechowywane, które jest poddrzewem danego drzewa.

Zazwyczaj przechowywałem około 500 niezrównoważonych drzew podwójnych o wysokości mniejszej niż 50.

EDYTOWAĆ

Moja aplikacja jest rodzajem sprawdzania modelu przy użyciu pewnego rodzaju zapamiętywania. Wyobrazić, że mają stan i z następujących wzorów: i z będący złożoną podstruktura i sobie wyobrazić, że najpierw chce wiedzieć, posiada w s . Sprawdzam, czy ϕ się utrzymuje i po długim procesie stwierdzam, że tak jest. Teraz chcę wiedzieć, czy g trzyma si . Chciałbym przypomnieć fakt, że f posiada i zauważyć, że g f tak, że może pochodzić g w s prawie natychmiast.f = ϕ g = ( ϕ ψ ) ϕ fsfa=ϕsol=(ϕψ)ϕfasϕsolsfasolfasols
I odwrotnie, jeśli udowodniłem, że nie utrzymuje wt , to chcę powiedzieć, że f nie utrzymuje wt prawie natychmiast.soltfat

Możemy budować częściowe porządki na formułach i mieć iff g f . Dla każdego stanu s , możemy przechowywać dwa zestawy wzorów; L ( s ) przechowuje maksymalne formuły, które przechowują, a l ( s ) przechowuje minimalne formuły, które nie przechowują. Teraz biorąc pod uwagę stan si formułę g , widzę, czy f L ( s ) , f g , czy czy f l ( s )solfasolfasL.(s)l(s)ssolfaL.(s),fasol w którym to przypadku skończę i wiem bezpośrednio, czy g trzyma w s .fal(s),solfasols

Obecnie i l są implementowane jako listy i nie jest to oczywiście optymalne, ponieważ muszę iterować wszystkie zapisane formuły osobno. Gdyby moje formuły były sekwencjami, a jeśli częściowa kolejność była „jest przedrostkiem”, wtedy trie mogłaby okazać się znacznie szybsza. Niestety moje formuły mają strukturę drzewiastą opartą na ¬ , , operatorze modalnym i twierdzeniach atomowych.L.l¬,

Jak wskazują @Raphael i @Jack, mógłbym sekwencjonować drzewa, ale obawiam się, że to nie rozwiąże problemu, ponieważ interesująca mnie cząstkowa kolejność nie odpowiada „przedrostkowi”.

Abdallah
źródło
Szybki pomysł: czy próbowałeś sekwencjonować drzewa (wykonać przechodzenie w kolejności, odpowiednio wyświetlić odwiedzone węzły i dodać specjalne elementy do ruchów w górę lub w dół) i przechowywać je w trie? Oczywiście w pewnym sensie pozwoliłoby to jedynie na sprawdzenie lewych poddrzewa.
Raphael
2
Co się stanie, jeśli użyjesz po prostu serializacji drzew o następującej właściwości: T jest poddrzewem T wtedy i tylko wtedy, gdy S ( T ) jest podciągiem S ( T ) ? Zbudowanie takiego S jest proste [jeśli najpierw znajdziesz kanoniczną formę swoich drzew]. Następnie twoje pytanie jest równoważne dopasowywaniu podciągów, co jest szeroko badanym problemem w zakresie strunologii. S.T.T.S.(T.)S.(T.)S.
Jukka Suomela,
1
Spójrz na indeksowanie terminów .
starblue
1
Innym szybkim pomysłem byłoby przechowywanie wszystkich drzew t1, t2, .. w jednym dużym drzewie T, pamiętając dla każdej krawędzi zbiór drzew, których jest częścią. Następnie, aby ustalić, czy f jest poddrzewem jednego z przechowywanych drzew, najpierw należy ustalić, czy f jest poddrzewem w T, a jeśli tak, to przeciąć wszystkie zestawy etykiet krawędzi tego poddrzewa. Odpowiedź brzmi: tak, jeśli skrzyżowanie nie jest puste. (Możesz także połączyć dwa kroki).
Martin B.

Odpowiedzi:

5

Może chcesz wypróbować g-try . Jest to zasadniczo struktura danych, której szukasz, ale zaprojektowana do użytku z ogólnymi wykresami zamiast tylko z drzewami. Jako taki, nie jestem pewien, czy próby mają dobre gwarancje teoretyczne - myślę, że wykorzystują algorytm kanonizacji grafów jako podprogram - ale w praktyce wydają się działać dobrze.

(Nie bój się, że połączony artykuł dotyczy „motywów sieciowych w sieciach biologicznych”: g-trie to doskonale dobra abstrakcyjna struktura danych dla grafów.)

Joshua Grochow
źródło
4

Szczególną formą tego jest wytrwałość : patrz artykuły Tworzenie struktur danych trwałych przez Driscoll, Sarnak, Sleator i Tarjan oraz Planarna lokalizacja punktu za pomocą drzew ciągłego wyszukiwania Sarnak i Tarjan, które przechowują rodziny powiązanych drzew.

Jacek
źródło
1
Dziękuję za referencje. W tej chwili nie mogę uzyskać dostępu do tworzenia struktur danych , ale jestem nieco zaznajomiony z pojęciem trwałości. Jednak nie widzę, jak mogę użyć uporu, aby rozwiązać mój problem. Naprawdę chcę używać słowników, które mapują drzewa na logiczne, a to samo drzewo może być kluczem do różnych wartości w różnych słownikach.
Abdallah
1
Ponieważ nie byłem pewien, jaka jest twoja aplikacja, uruchomiłem twoją analogię do prób, które przechowują ciągi znaków, udostępniając prefiksy. Twój komentarz, że „to samo drzewo może być kluczem do różnych wartości w różnych słownikach” również nie pasuje do prób. Być może potrzebujesz tylko kolekcji podpisów dla drzewa (i wszystkich jego poddrzewa), które możesz sprawdzić? (np. używając liczb katalońskich dla drzew binarnych lub kodów Prufer dla drzew oznaczonych.)
Jack
1

Brzmi to trochę jak las ( rozrzucone lasy ) ...

Amortyzuje koszt wstawienia za pomocą techniki zwanej zgrupowaniem według rangi i operacji wyszukiwania z użyciem kompresji ścieżki . Wiem, że istnieje również trwała wersja tej struktury opracowana przez Sylvaina Conchona i Jean-Christophe Filliâtre, ale nie mam pojęcia, czy jest to ta sama, o której wspomina Jack ...

Rehno Lindeque
źródło
0

W „Purely Functional Data Structures” (1998) Chris Okasaki proponuje próby drzew binarnych z wykorzystaniem agregacji typów (10.3.2).

Nie wiem, czy to natychmiast pomaga; podane tam rozwiązanie może nie być możliwe do wdrożenia bezpośrednio.

Raphael
źródło
0

W języku programowania: jeśli utworzysz drzewa z typowych podwyrażeń / drzew / DAG, uzyskasz ładny kompaktowy model. Tak ukierunkowane wykresy acykliczne. Wtedy wystarczyłby zestaw drzew.

drzewo klasy publicznej {Operacja na łańcuchach znaków; Drzewo [] poddrzewa;

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;
}

...}

Map commonSubExpressions = new HashMap ();

Tree get (String expressionSyntax) {Tree t = new Tree (); t.operacja = ...; t.subtrees = ... wywołanie rekurencyjne w celu uzyskania podwyrażeń; Drzewo t2 = commonSubExpressions.get (t); if (t2 == null) {t2 = t; commonSubExpressions.put (t2, t2); } zwróć t2; }}

Joop Eggen
źródło