樹的理解(五):Trie

Trie,又稱前綴樹或字典樹,用於判斷字符串是否存在或者是否具有某種字符串前綴。

實現 Trie (前綴樹)

https://leetcode-cn.com/problems/implement-trie-prefix-tree/

二叉樹的每個節點存放兩個指針,left指向左子樹的頭結點,right指向了右子樹的頭結點,這兩個指針都爲Node類型;
相對於二叉樹,前綴樹的節點也要存指針,指向其他子節點。那麼對於這種類型的指針該如何設計呢,如果是要設計與字符串相關的前綴樹(假設字符的範圍爲a-z),Node類中只需要維護一個指針數組,大小爲26(對應26個英文字母),該數組也是Node類型,用來子節點的指針,很明顯,前綴樹是一個多叉樹。
除了指針外,還要維護一個類型爲boolean的變量,來判斷節點是否爲葉子節點。

那麼對於前綴樹的insert方法來說,不需要真正的插入字符串每個字符的值,只需要在每個節點中將字符所對應下標的位置上插入一個新的節點,就可以表示存在該字符,在前綴樹表示的字符串最後的一個字符中,要將isLeaf變量設爲true,表示字符串到此結束。

對於search方法來說,逐一判斷前綴樹中是否存在字符串的所有字符即可,如果前綴樹中所對應字符串指定字符的節點爲null,那麼表示不存在該字符串,直到判斷字符串的最後一個字符,並判斷isLeaf是否爲true。(表示字符串結束)

對於startsWith方法來說,逐一判斷前綴樹中是否存在字符串的所有字符即可,如果前綴樹中所對應字符串指定字符的節點爲null,那麼表示不存在該字符串,直到判斷字符串的最後一個字符即可。無需判斷isLeaf。

class Trie {

    private class Node{
        Node[] childs = new Node[26];
        boolean isLeaf;
    }

    private Node root = new Node();

    /** Initialize your data structure here. */
    public Trie() {}
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        insert(word,root);
    }
    private void insert(String word,Node node) {
        if(node == null) return;
        if(word.length() == 0) {
            node.isLeaf = true;
            return;
        }
        int index = findCharIndex(word.charAt(0));
        if(node.childs[index] == null) 
            node.childs[index] = new Node();
        insert(word.substring(1),node.childs[index]);        
    }
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        return search(word,root);
    }

    private boolean search(String word,Node node) {
        if(node == null) return false;
        if(word.length() == 0) return node.isLeaf;
        int index = findCharIndex(word.charAt(0));
        return search(word.substring(1),node.childs[index]);
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        return startsWith(prefix,root);
    }
    private boolean startsWith(String prefix,Node node) {
        if(node == null) return false;
        if(prefix.length() == 0) return true;
        int index = findCharIndex(prefix.charAt(0));
        return startsWith(prefix.substring(1),node.childs[index]);
    }
    //找到指定字符在節點中的index
	private int findCharIndex(char c) {
        return c - 'a';
    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章