Menu
Coddy logo textTech

Trie (drzewo prefiksowe)

Ostatnia aktualizacja

Trie (czytaj „traj”), czyli drzewo prefiksowe, przechowuje zbiór napisów według ich znaków: każda krawędź ma etykietę w postaci znaku, a ścieżka od korzenia tworzy prefiks. Słowa o wspólnym prefiksie korzystają z tych samych węzłów, więc „car”, „card” i „care” używają tej samej ścieżki c-a-r. Naciśnij Odtwórz powyżej i zobacz, jak słowa są wstawiane znak po znaku i rozgałęziają się tylko tam, gdzie się różnią.

Wyszukiwanie przechodzi przez jeden węzeł na znak, więc znalezienie słowa o długości m zajmuje O(m) bez względu na to, ile słów zawiera trie. Dzięki temu trie świetnie nadaje się do autouzupełniania, sprawdzania pisowni i wyszukiwania po prefiksie.

Złożoność czasowa i pamięciowa

OperacjaZłożonośćUwagi
WstawianieO(m)m = długość słowa
WyszukiwanieO(m)Jeden krok na znak
Zapytanie o prefiksO(m)Przejście do węzła prefiksu
PamięćO(total chars)Wspólne prefiksy przechowywane tylko raz

Krok po kroku (wstawianie)

KrokCo się dzieje
1Zacznij od korzenia.
2Dla każdego znaku słowa szukaj pasującej krawędzi do dziecka.
3Jeśli istnieje, przejdź po niej (korzystając ze wspólnego prefiksu).
4Jeśli nie, utwórz nowy węzeł potomny dla tego znaku.
5Po ostatnim znaku oznacz ten węzeł jako koniec słowa.

Przykład krok po kroku

Wstawiamy ["car", "card", "care"] do pustego trie:

KrokStrukturaDziałanie
Wstaw carroot → c → a → r✓Nie ma pasujących dzieci, więc utwórz c, a, r i oznacz r jako koniec słowa.
Wstaw cardroot → c → a → r✓ → d✓Użyj istniejącej ścieżki c-a-r, potem utwórz jedno nowe dziecko d i oznacz je jako koniec słowa.
Wstaw careroot → c → a → r✓ → {d✓, e✓}Użyj c-a-r, odgałęź się od r nowym dzieckiem e i oznacz e jako koniec słowa.
Szukaj careroot → c → a → r → e✓Przejdź przez c, a, r, e; ostatni węzeł jest oznaczony jako koniec słowa, więc care jest w trie.
Szukaj caroot → c → aŚcieżka istnieje, ale a nie jest oznaczony jako koniec słowa, więc ca jest prefiksem, a nie zapisanym słowem.

Kiedy używać trie

Używaj, gdyUnikaj, gdy
Potrzebujesz zapytań o prefiks lub autouzupełniania w zbiorze napisów.Wyszukujesz tylko całe klucze: tablica mieszająca jest szybsza i lżejsza.
Wiele zapisanych słów ma wspólne prefiksy, więc węzły są współdzielone.Klucze są długie i rzadko się pokrywają, co marnuje jeden węzeł na znak.
Chcesz otrzymywać klucze w kolejności posortowanej przez przejście drzewa.Pamięci jest mało: wskaźniki na dzieci w każdym węźle dodają spory narzut.
Koszt wyszukiwania ma zależeć od długości klucza, a nie od rozmiaru danych.Alfabet jest ogromny (np. cały Unicode), a dzieci są przechowywane gęsto.

Trie (Prefix Tree): kod

Przejrzysta, gotowa do uruchomienia implementacja algorytmu Trie (Prefix Tree) w językach: Python, JavaScript, Java, C++, C. Wybierz język, skopiuj kod albo otwórz go od razu w edytorze online Coddy.

Trie (Prefix Tree): kod (Python)

Python
1class TrieNode:2    def __init__(self):3        self.children = {}4        self.is_word = False5
6
7class Trie:8    def __init__(self):9        self.root = TrieNode()10
11    def insert(self, word):12        node = self.root13        for ch in word:14            node = node.children.setdefault(ch, TrieNode())15        node.is_word = True16
17    def search(self, word):18        node = self._walk(word)19        return node is not None and node.is_word20
21    def starts_with(self, prefix):22        return self._walk(prefix) is not None23
24    def _walk(self, s):25        node = self.root26        for ch in s:27            if ch not in node.children:28                return None29            node = node.children[ch]30        return node31
32
33trie = Trie()34for word in ["car", "card", "care", "dog"]:35    trie.insert(word)36
37print("search(card):     ", trie.search("card"))38print("search(ca):       ", trie.search("ca"))39print("starts_with(ca):  ", trie.starts_with("ca"))40print("starts_with(do):  ", trie.starts_with("do"))41print("starts_with(cat): ", trie.starts_with("cat"))
Uruchom ten kod w edytorze Python online

Trie: najczęstsze pytania

Do czego służy trie?
Trie napędza funkcje oparte na prefiksach: autouzupełnianie i podpowiedzi wyszukiwania, sprawdzanie pisowni, tablice routingu IP i wyszukiwanie w słownikach. Wszędzie tam, gdzie trzeba szybko odpowiadać na pytanie „czy któreś zapisane słowo zaczyna się od tego prefiksu?”, trie sprawdza się znakomicie.
Jaka jest złożoność czasowa trie?
Wstawianie, wyszukiwanie i zapytania o prefiks działają w czasie O(m), gdzie m to długość słowa lub prefiksu, niezależnie od liczby zapisanych słów. Ceną jest pamięć: trie może zajmować dużo miejsca, choć wspólne prefiksy są przechowywane tylko raz.
Czym różni się trie od tablicy mieszającej?
Tablica mieszająca oferuje średnio wyszukiwanie całych kluczy w O(1), ale nie odpowie na zapytania o prefiks. Trie jest nieco wolniejsze przy pojedynczym wyszukiwaniu, za to naturalnie obsługuje wyszukiwanie po prefiksie, przechodzenie w kolejności i autouzupełnianie, dlatego to ono jest wybierane w takich zastosowaniach.
Kiedy użyć trie zamiast drzewa BST?
Wybierz trie, gdy kluczami są napisy i potrzebujesz wyszukiwania po prefiksie: każda operacja kosztuje O(m) względem długości klucza, a zrównoważone drzewo BST kosztuje O(m log n), bo każde porównanie przechodzi przez napis, a porównań jest log n. Drzewo BST jest lepszym wyborem, gdy klucze nie są napisami albo gdy narzut pamięci ma większe znaczenie niż szybkość wyszukiwania po prefiksie.
Jak oznacza się koniec słowa w trie?
Każdy węzeł ma flagę końca słowa, ustawianą tylko wtedy, gdy w tym miejscu kończy się całe wstawione słowo. Bez niej nie da się odróżnić zapisanego słowa od samego prefiksu: na przykład po wstawieniu card węzeł dla car istnieje, ale powinien być zgłoszony jako słowo tylko wtedy, gdy car też zostało wstawione.
Czy trie zawsze oszczędza pamięć dzięki wspólnym prefiksom?
Nie zawsze. Współdzielenie pomaga tylko wtedy, gdy wiele kluczy się pokrywa; przy długich, różnych kluczach trie może zużyć znacznie więcej pamięci niż zbiór oparty na haszowaniu, bo każdy znak staje się osobnym węzłem ze wskaźnikami na dzieci. Jeśli liczy się pamięć, skompresowane drzewo radix scala łańcuchy węzłów z jednym dzieckiem i zmniejsza ten narzut.
Ilustracja języków programowania w Coddy

Opanuj algorytmy z Coddy

ZACZNIJ