字首樹
概念:
簡述:又名單詞查詢樹,tries樹,一種多路樹形結構,常用來操作字串(但不限於字串),和hash效率有一拼(二者效率高低是相對的,後面比較)。
性質:不同字串的相同字首只儲存一份。
操作:查詢,插入,刪除等。
舉個例子:
假設有這麼幾個單詞
abcd
abc
abd
bcq
edj
字首樹畫出如下
如上圖可以看出,abcd等字元是在邊上的,a的那條邊和指向的節點我們可以看成一個整體,儲存的資訊是在節點上
定義的資料結構:
//節點
public static class TrieNode{
//以此節點結尾
int end;
//走過的路徑的次數,可以理解為一個節點和指向 它的路徑的值
int path;
//節點
private TrieNode[] arr;
public TrieNode(){
end = 0;
path = 0;
arr= new TrieNode[26];
}
}
操作:
插入:
先建立一個根節點,根節點代表起點,起點可以有26條不同的路,代表26個字母,你可以想想一個根節點走出26個字元的路徑。然後用 index = chs[i] - 'a' 來計算屬於哪條路,在這裡解釋一下,-'a' 減去的是'a'的阿斯克碼,比如傳進來的是b 就相當於用b的阿斯克碼減去a的阿斯克碼,求出的就是由當前結點出去的那條路徑,其中end代表以當前結點結尾,path代表經過當前結點的個數,如上所說,當前結點和指向它的路徑可以看成一個整體,比如一個節點,指向它的由a,b,c,它的path就是3,知道了變數的意思,插入就簡單了,就判斷現在要加入的節點之前有沒有,沒有就加入,加完之後,把尾節點的end++即可
程式碼:
public static class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String word) {
if (word == null) {
return;
}
char[] chs = word.toCharArray();
TrieNode node = root;
int index = 0;
for (int i = 0; i < chs.length; i++) {
index = chs[i] - 'a';
if (node.arr[index] == null) {
node.arr[index] = new TrieNode();
}
node = node.arr[index];
node.path++;
}
node.end++;
}
}
查詢:
查詢的整體操作和插入類似,查詢就隨著字串向下查詢,如果查的當前節點沒有,就返回false,直到查完,看尾節點的end是否大於零,大於零說明有該字元,如果為0就說明沒有,比如有字串abcd,你要查有沒有abc,雖然一直能查到c,但是c的end不是1,所以沒有
程式碼:
public static class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
public boolean search(String word) {
if (word == null) {
return false;
}
char[] chs = word.toCharArray();
TrieNode node = root;
int index = 0;
for (int i = 0; i < chs.length; i++) {
index = chs[i] - 'a';
if (node.arr[index] == null) {
return false;
}
node = node.arr[index];
}
return node.end != 0;
}
}
刪除:
刪除就判斷當前節點的--path是否為0,為0就說明要刪除的就是這個路徑,而且只有要刪除的那一個字串在這條大路徑上,刪除就行,另一種情況,abcd,abc,要刪除abc,就相當於大路徑還在,只不過把每個節點的--path,然後c的end--就行了
程式碼:
public static class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
public void delete(String word) {
if (search(word)) {
char[] chs = word.toCharArray();
TrieNode node = root;
int index = 0;
for (int i = 0; i < chs.length; i++) {
index = chs[i] - 'a';
if (node.arr[index].path-- == 1) {
node.arr[index] = null;
return;
}
node = node.arr[index];
}
node.end--;
}
}
查詢是否包含此字首:
如果當前結點的下一個節點不為空,就一直找下去,為空就返回0,查到最後就,返回當前結點的path值,代表有幾個字串有此字首
程式碼:
public static class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
public int prefixNumber(String pre) {
if (pre == null) {
return 0;
}
char[] chs = pre.toCharArray();
TrieNode node = root;
int index = 0;
for (int i = 0; i < chs.length; i++) {
index = chs[i] - 'a';
if (node.arr[index] == null) {
return 0;
}
node = node.[index];
}
return node.path;
}
}
相關文章
- 【演算法】字首樹演算法
- 字典樹(字首樹)簡單實現
- 字首樹及其Java實現Java
- 資料結構丨字首樹資料結構
- 樹上字首和與差分
- 資料結構基礎--字首樹&&字尾樹資料結構
- 208. 實現 Trie (字首樹)-pythonPython
- 資料結構的故事之二叉樹, 字首樹, N叉樹資料結構二叉樹
- 演算法之字首樹——最大異或和演算法
- ABC353E字典樹處理最長公共字首
- [leetcode/lintcode 題解] 微軟 面試題:實現 Trie(字首樹)LeetCode微軟面試題
- 字首和與二維字首和
- 【資料結構與演算法】Trie(字首樹)模板和例題資料結構演算法
- 字首和
- (Day4)字首和&二維字首和
- 《演算法筆記》5. 字首樹、桶排序、排序演算法總結演算法筆記排序
- P4551 最長異或路徑(樹上字首異或01-trie)
- Python字串字首Python字串
- Leetcode 327. 區間和的個數 (字首和 + 離散化 + 樹狀陣列)LeetCode陣列
- 關於區間操作查詢(字首和與差分)+樹狀陣列基礎陣列
- mysql建立字首索引MySql索引
- 最長公共字首
- 高維字首和
- 字首和&差分
- 字首和 & 差分
- mysql索引之字首索引MySql索引
- 高維字首和SOSDP
- 字首和與差分
- 組合數字首和
- Golang判斷url字首Golang
- LeetCode最長公共字首(Python)LeetCodePython
- 14.最長公共字首
- 1.Prefix字首和【模板】
- 14. 最長公共字首
- 高維字首和(SOS DP)
- 淺記高維字首和
- nginx反向代理配置去除字首Nginx
- 力扣最長公共字首力扣