目錄trie是乙個多叉樹,trie專門為處理字串而設計的。使用我們之前實現的二分搜尋樹來查詢字典中的單詞,查詢的時間複雜度為o(logn),如果有100萬(220)個單詞,則logn大約等於20,但是使用trie這種資料結構,查詢每個條目的時間複雜度,和一共有多少個條目無關!時間複雜度為o(w),w為被查詢單詞的長度!大多數單詞的長度小於10。
trie將整個字串以字母為單位,乙個乙個拆開,從根節點開始一直到葉子節點去遍歷,就形成了乙個單詞,下圖中的trie就儲存的四個單詞(cat,dog,deer,panda)
每個節點有26個字母指向下個節點的指標,考慮不同的語言,不同的情境,比如現在這個26個字元是沒有包含大寫字母的,如果需要包含大寫字母,則需要讓每個節點有52個指向下個節點的指標,如果現在要加入郵箱呢?所以這裡描述為每個節點有若干個指向下個節點的指標。
由於很多單詞可能是另外乙個單詞的字首,比如pan就是panda的字首,那麼再trie中如何儲存呢?所以我們應該對節點新增乙個識別符號,判斷該節點是否是某個單詞的結尾,某乙個單詞的結尾只靠葉子節點是不能區別出來的,因此我們再設計node節點時,應該新增乙個isword,判斷該節點是否是單詞的結尾。
在建立trie之前,我們需要先設計trie的節點類,根據上面說的,每個節點都有若干個指向下個節點的指標,還需要乙個isword來判斷是否是單詞的結尾,**實現如下:
//設計trie的節點類
private class node
//無參構造:預設當前節點不是單詞的結尾
public node()
}
現在就讓我們來實現乙個trie
public class trie
//無參構造:預設當前節點不是單詞的結尾
public node()
}private node root;
private int size;
public trie()
// 獲得trie中儲存的單詞數量
public int getsize()
}
trie的新增操作:新增的是乙個字串,要把這個字串拆成乙個乙個字元,把這乙個乙個字元作為乙個乙個節點,存入trie中。
//向trie中新增乙個新的單詞word
public void add(string word)
cur = cur.next.get(c);
}//對新增的新單詞遍歷結束後,判斷當前節點是否為單詞的結尾,如果不是我們才對size加一,並且維護當前節點的isword
if (! cur.isword)
}
//tire的查詢操作
public boolean contains(string word)
cur = cur.next.get(c);
}return cur.isword;
}
與查詢型別,我們可以寫乙個是否存在以某個單詞為字首的單詞
//查詢在trie中是否有單詞以prefix為字首
public boolean isprefix(string prefix)
return true;
}
這裡對比二分搜尋樹和trie的效能,仍然是使用的以新增和統計《傲慢與偏見》這本書為例,關於該測試用例中的檔案工具類,和《傲慢與偏見》文件,請前往我之前寫的 集合和對映 進行獲取。
通過上面測試**可以看出,其實資料量不大的情況下,對於乙個隨機字串的集合,使用二分搜尋書和trie進行新增和查詢操作,差別是不大的,如果我們加入的資料是有序的,這時二分搜尋樹就會退化成煉表,時間複雜度就為o(n),執行效率是很低的,但是trie並不受影響,我們可以對words進行排序後,在看一下執行結果:
通過上面的測試,可以看出對有序的資料進行新增和查詢操作,差距是特別大的。
我們可以看到leetcode官網上的208好問題,就是實現乙個trie
其實從題目描述中就可以看出,這個問題中的三個方法就是我們實現的add(),contains(),isprefix()操作,直接將我們寫的**改個方法名字提交就可以通過了。
我們再來看一道leetcode上的211號問題:新增與搜尋單詞
通過題目描述,我們會發現只是查詢操作和我們實現的trie有所不同,新增操作沒有發改變。由於字元'.'可以代表任何乙個字母,所以我們對於'.',需要遍歷所有的可能。
public boolean search(string word)
private boolean match(node node, string word, int index)
else
}return false;}}
**提交到leetcode後,就會提示通過了
我們再來看看leetcode上的677號問題:map sum pairs(鍵值對映)
根據題目描述,我們可以理解為:對映中儲存的是單詞和權重值。sum()方法是求得包含這個字首單詞得權重和
**實現如下:
//設計節點類
private class node
public node()
}private node root;
public mapsum()
//新增操作和我們實現的字典樹中的新增操作型別
public void insert(string word,int val)
cur = cur.next.get(c);
}cur.value = val;
}//求字首為prefix的權重和
public int sum(string prefix)
cur = cur.next.get(c);
}return sum(cur);
}private int sum(node node)
return res;
}
leetcode上的提交結果:
Trie 字典樹 字首樹
所有的php檔案放到同乙個目錄下 trie charmap.php map.php stdmap.php trie.php trienode.php index.php test.php words.txt trienode.php class trienode 字典樹是利用字串的公共字首來節約儲存...
Trie樹,字典樹,字首樹
trie樹,字典樹,字首樹,都是同一顆樹,雜湊樹的變種題目鏈結 常用於文字的詞頻統計 它的特點就是,空間占用小,查詢快 它的儲存方式如下圖所示 對於從樹的根節點走到每乙個黑色節點所經過的路徑,如果將路徑上的字母都連起來的話,就都對應著詞典中的乙個單詞 trie樹,分別有插入,查詢和刪除3種操作,插入...
Trie樹 字典樹 字首樹
trie樹,即字典樹,又稱單詞查詢樹或鍵樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計和排序大量的字串 但不僅限於字串 所以經常被搜尋引擎系統用於文字詞頻統計。它的優點是 最大限度地減少無謂的字串比較,查詢效率比雜湊表高。trie的核心思想是空間換時間。利用字串的公共字首來降低查詢時間的...