Trie 字典樹 字首樹

2022-06-18 21:30:17 字數 3683 閱讀 2348

目錄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的核心思想是空間換時間。利用字串的公共字首來降低查詢時間的...