Menu
Coddy logo textTech

Trie (Präfixbaum)

Zuletzt aktualisiert

Ein Trie (ausgesprochen „trai"), oder Präfixbaum, speichert eine Menge von Zeichenketten anhand ihrer Zeichen: Jede Kante ist mit einem Zeichen beschriftet, und ein Pfad von der Wurzel buchstabiert ein Präfix. Wörter mit gemeinsamem Präfix teilen sich dieselben Knoten, sodass „car", „card" und „care" alle den Pfad c-a-r wiederverwenden. Drücke oben auf Abspielen, um zu sehen, wie Wörter Zeichen für Zeichen eingefügt werden und sich nur dort verzweigen, wo sie sich unterscheiden.

Da Suchvorgänge einen Knoten pro Zeichen durchlaufen, dauert die Suche nach einem Wort der Länge m O(m), unabhängig davon, wie viele Wörter der Trie enthält. Das macht Tries ideal für Autovervollständigung, Rechtschreibprüfung und Präfixsuche.

Zeit- und Speicherkomplexität

OperationKomplexitätAnmerkungen
EinfügenO(m)m = Länge des Worts
SuchenO(m)Ein Schritt pro Zeichen
PräfixabfrageO(m)Bis zum Präfixknoten laufen
SpeicherO(total chars)Gemeinsame Präfixe werden nur einmal gespeichert

Schritt für Schritt (Einfügen)

SchrittWas passiert
1Beginne beim Wurzelknoten.
2Suche für jedes Zeichen des Worts nach einer passenden Kind-Kante.
3Wenn sie existiert, folge ihr (und verwende das gemeinsame Präfix wieder).
4Wenn nicht, erstelle einen neuen Kindknoten für dieses Zeichen.
5Markiere den Knoten nach dem letzten Zeichen als Wortende.

Durchgerechnetes Beispiel

Einfügen von ["car", "card", "care"] in einen leeren Trie:

SchrittStrukturAktion
car einfügenroot → c → a → r✓Es gibt keine passenden Kinder, also erstelle c, a, r und markiere r als Wortende.
card einfügenroot → c → a → r✓ → d✓Verwende den vorhandenen Pfad c-a-r wieder, erstelle dann ein neues Kind d und markiere es als Wortende.
care einfügenroot → c → a → r✓ → {d✓, e✓}Verwende c-a-r wieder, verzweige von r mit einem neuen Kind e und markiere e als Wortende.
care suchenroot → c → a → r → e✓Laufe c, a, r, e ab; der letzte Knoten ist als Wortende markiert, also ist care vorhanden.
ca suchenroot → c → aDer Pfad existiert, aber a ist nicht als Wortende markiert, also ist ca ein Präfix, aber kein gespeichertes Wort.

Wann man einen Trie verwendet

Verwenden, wennVermeiden, wenn
Du Präfixabfragen oder Autovervollständigung über eine Menge von Zeichenketten brauchst.Du nur Suchen nach ganzen Schlüsseln brauchst - eine Hashtabelle ist schneller und leichter.
Viele gespeicherte Wörter gemeinsame Präfixe teilen, sodass Knoten wiederverwendet werden.Die Schlüssel lang sind und sich selten überschneiden, wodurch pro Zeichen ein Knoten verschwendet wird.
Du willst, dass Schlüssel per Durchlauf in sortierter Reihenfolge zurückgegeben werden.Der Speicher knapp ist - Kind-Zeiger pro Knoten verursachen erheblichen Mehraufwand.
Die Suchkosten von der Schlüssellänge abhängen sollen, nicht von der Datensatzgröße.Das Alphabet riesig ist (z. B. das gesamte Unicode) und Kinder dicht gespeichert werden.

Trie (Prefix Tree)-Code

Eine saubere, lauffähige Trie (Prefix Tree)-Implementierung in Python, JavaScript, Java, C++, C. Wähle eine Sprache, kopiere den Code oder öffne ihn vorgeladen im Coddy-Playground.

Trie (Prefix Tree)-Code in 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"))
Führe diesen Code im Python-Playground aus

Trie-FAQ

Wofür wird ein Trie verwendet?
Tries treiben präfixbasierte Funktionen an: Autovervollständigung und Suchvorschläge, Rechtschreibprüfung, IP-Routing-Tabellen und Wörterbuchsuchen. Überall, wo du schnell beantworten musst „beginnt ein gespeichertes Wort mit diesem Präfix?", glänzt ein Trie.
Wie ist die Zeitkomplexität eines Tries?
Einfügen, Suchen und Präfixabfragen laufen alle in O(m), wobei m die Länge des Worts oder Präfixes ist - unabhängig davon, wie viele Wörter gespeichert sind. Der Kompromiss ist der Speicher: Ein Trie kann viel Platz beanspruchen, obwohl gemeinsame Präfixe nur einmal gespeichert werden.
Was ist der Unterschied zwischen einem Trie und einer Hashtabelle?
Eine Hashtabelle bietet durchschnittlich O(1)-Suche nach ganzen Schlüsseln, kann aber keine Präfixabfragen beantworten. Ein Trie ist pro Suche etwas langsamer, unterstützt aber von Natur aus Präfixsuche, geordneten Durchlauf und Autovervollständigung - der Grund, warum er dafür bevorzugt wird.
Wann sollte ich einen Trie statt eines binären Suchbaums verwenden?
Verwende einen Trie, wenn deine Schlüssel Zeichenketten sind und du Präfixsuchen brauchst: Er läuft in O(m) pro Operation über die Schlüssellänge, während ein balancierter BST O(m log n) kostet, weil jeder Vergleich die Zeichenkette durchläuft und es log n davon gibt. Ein BST ist die bessere Wahl, wenn die Schlüssel nicht zeichenkettenartig sind oder der Speicheraufwand wichtiger ist als die Präfixgeschwindigkeit.
Wie behandelt man das Ende eines Worts in einem Trie?
Jeder Knoten trägt eine Wortende-Markierung, die nur gesetzt wird, wenn dort ein vollständig eingefügtes Wort endet. Ohne sie könntest du ein gespeichertes Wort nicht von einem bloßen Präfix unterscheiden - nach dem Einfügen von card existiert der Knoten für car, sollte aber nur dann als Wort gemeldet werden, wenn car ebenfalls eingefügt wurde.
Sparen Tries durch das Teilen von Präfixen immer Speicher?
Nicht immer. Das Teilen hilft nur, wenn sich viele Schlüssel überschneiden; bei langen, unterschiedlichen Schlüsseln kann ein Trie weit mehr Speicher verbrauchen als eine Hash-Menge, da jedes Zeichen zu einem eigenen Knoten mit Kind-Zeigern wird. Wenn der Platz das Problem ist, führt ein komprimierter Radix-Baum Ketten mit einem einzigen Kind zusammen, um diesen Mehraufwand zu senken.
Coddy programming languages illustration

Meistere Algorithmen mit Coddy

LOS GEHT'S