Trie

Photo by Sabrina Mazzeo on Unsplash
Photo by Sabrina Mazzeo on Unsplash
Trie 是一種 k-ary search tree。它可以儲存大量的字串,並且提供有效率的字串搜尋。

Trie 是一種 k-ary search tree。它可以儲存大量的字串,並且提供有效率的字串搜尋。

Trie & TrieNode

Trie 一般會有兩個資料結構,一個是 Trie,另一個是 TrieNodeTrieNode 被用來建構整個 tree,而 Trie 只會有一個。TrieNode.terminates 表示從 root 到該 node 的 path 是一個 word。另外,TrieNode.character 不是必要的,因為可以從 parent 的 children 就可以得知該 node 代表的字元。root 不代表任何字元。

public class Trie {
    private final TrieNode root = new TrieNode();

    public Trie(ArrayList<String> list) {
        for (String word : list) {
            root.addWord(word);
        }
    }

    public Trie(String[] list) {
        for (String word : list) {
            root.addWord(word);
        }
    }

    public boolean contains(String prefix, boolean exact) {
        TrieNode lastNode = root;
        for (int i = 0; i < prefix.length(); i++) {
            lastNode = lastNode.getChild(prefix.charAt(i));
            if (lastNode == null) {
                return false;
            }
        }
        return !exact || lastNode.terminates();
    }

    public boolean contains(String prefix) {
        return contains(prefix, false);
    }

    public void addWord(String word) {
        root.addWord(word);
    }
}
public class TrieNode {
    private final HashMap<Character, TrieNode> children = new HashMap<>();
    private boolean terminates = false;
    private char character;

    public TrieNode() {
    }

    public TrieNode(char character) {
        this.character = character;
    }

    public char getChar() {
        return character;
    }

    public void addWord(String word) {
        if (word == null || word.isEmpty()) {
            return;
        }

        char firstChar = word.charAt(0);
        TrieNode child = getChild(firstChar);
        if (child == null) {
            child = new TrieNode(firstChar);
            children.put(firstChar, child);
        }

        if (word.length() > 1) {
            child.addWord(word.substring(1));
        } else {
            child.setTerminates(true);
        }
    }

    public TrieNode getChild(char c) {
        return children.get(c);
    }

    public boolean terminates() {
        return terminates;
    }

    public void setTerminates(boolean terminates) {
        this.terminates = terminates;
    }
}

複雜度

建立字典所需的時間複雜度為 O(\sum(w_{i})),其中 w_{i} 為 word[i] 的長度。

搜尋和插入一個 word 所需的時間複雜度為 O(w_{i})

空間複雜度為所有 node 的數量,所以是 O(\sum(w_{i}))

範例

下面的範例顯示,在插入 word 時,Trie 內部的變化。綠色表示該 node 的 terminates 設為 true。

參考

  • Gayle Laakmann McDowell, Cracking the Coding Interview, 6th Edition.
  • Trie, Wikipedia.
發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

You May Also Like
Photo by Léonard Cotte on Unsplash
Read More

Depth First Search (DFS)

深度優先搜尋(DFS)演算法是一種圖形搜尋演算法。從給定的一個點開始,它會先探索該點的一個相鄰點。再來,探索該相鄰點的一個相鄰點。這樣子一直探索下去,直到某的點沒有相鄰點時,它就會退回到上一個點,並探索該點的下一個相鄰點。它會一直這樣地探索下去,直到找到結果,或是探索完所有的點。
Read More
Photo by Pedro Lastra on Unsplash
Read More

Breadth First Search (BFS)

廣度優先搜尋(BFS)演算法是一種圖形搜尋演算法。從給定的一個點開始,它會先探索該點所有的相鄰點。再來,依序探索這些相鄰點的相鄰點。這樣子一層一層地探索下去,直到找到結果,或是探索完所有的點。
Read More
Photo by Simon Hermans on Unsplash
Read More

Priority Queue & Heap

Priority queue 是一個很好用的 data structure。它可以在常數時間內提供最大或最小值。在了解它之前,我們要先了解另一個 data structure 叫 heap。因為 priority queue 常常會用 heap 來實作。
Read More
Photo by Anthony DELANOIX on Unsplash
Read More

Union Find

Union Find data structure 又稱 disjoint set data structure。它是一個資料結構,用來儲存一堆 disjoint set。它提供兩個操作,一個是用來合併兩個 sets,另一個是用來尋找給定元素的 set。
Read More
Photo by Folco Masi on Unsplash
Read More

Binary Search Tree

二元搜尋樹(Binary search tree, BST)是一種二元樹(binary tree)。它提供了一些有用操作,包含 search、insert、delete、minimum、maximum、successor 和 predecessor。
Read More