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 Folco Masi on Unsplash
Read More

Binary Search Tree

二元搜尋樹(Binary search tree, BST)是一種二元樹(binary tree)。它提供了一些有用操作,包含 search、insert、delete、minimum、maximum、successor 和 predecessor。
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