成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java 數(shù)據(jù)結(jié)構(gòu)與算法中的字典樹(shù),你學(xué)會(huì)了嗎?

開(kāi)發(fā) 前端
在計(jì)算機(jī)科學(xué)中,字典樹(shù)(Trie)也被稱為”單詞查找樹(shù)“或”數(shù)字樹(shù)“,有時(shí)候也被稱為基數(shù)樹(shù)或前綴樹(shù)(因?yàn)榭梢酝ㄟ^(guò)前綴的方式進(jìn)行索引)。—— 它是一種搜索樹(shù),一種已排序的數(shù)據(jù)結(jié)構(gòu),通常用于存儲(chǔ)動(dòng)態(tài)集或鍵為字符串的關(guān)聯(lián)數(shù)組。

一、前言

Trie 的歷史

字典樹(shù) Trie 這個(gè)詞來(lái)自于 retrieval,于 1912 年,Axel Thue 首次抽象地描述了一組字符串?dāng)?shù)據(jù)結(jié)構(gòu)的存放方式為 Trie 的想法。這個(gè)想法于 1960 年由 Edward Fredkin 獨(dú)立描述,并創(chuàng)造了 Trie 一詞。你看看,多少程序員為了一個(gè)詞、方法名、屬性名,想破腦袋!

二、字典樹(shù)數(shù)據(jù)結(jié)構(gòu)

在計(jì)算機(jī)科學(xué)中,字典樹(shù)(Trie)也被稱為”單詞查找樹(shù)“或”數(shù)字樹(shù)“,有時(shí)候也被稱為基數(shù)樹(shù)或前綴樹(shù)(因?yàn)榭梢酝ㄟ^(guò)前綴的方式進(jìn)行索引)。—— 它是一種搜索樹(shù),一種已排序的數(shù)據(jù)結(jié)構(gòu),通常用于存儲(chǔ)動(dòng)態(tài)集或鍵為字符串的關(guān)聯(lián)數(shù)組。

與二叉查找樹(shù)不同,鍵不是直接保存在節(jié)點(diǎn)中,而是由節(jié)點(diǎn)在樹(shù)中的位置決定。一個(gè)節(jié)點(diǎn)的所有子孫都有相同的前綴,也就是這個(gè)節(jié)點(diǎn)對(duì)應(yīng)的字符串,而根節(jié)點(diǎn)對(duì)應(yīng)空字符串。一般情況下,不是所有的節(jié)點(diǎn)都有對(duì)應(yīng)的值,只有葉子節(jié)點(diǎn)和部分內(nèi)部節(jié)點(diǎn)所對(duì)應(yīng)的鍵才有相關(guān)的值。

圖片

  • 這是一個(gè)把 battle 單詞字符串,按照字母拆分到字典樹(shù)進(jìn)行存放的圖。
  • 鍵標(biāo)注在節(jié)點(diǎn)中,值標(biāo)注在節(jié)點(diǎn)之下。每一個(gè)完整的英文單詞對(duì)應(yīng)一個(gè)特定的整數(shù)。也就是26個(gè)字母對(duì)應(yīng)的 ASCII 轉(zhuǎn)換后的值。

三、字典樹(shù)結(jié)構(gòu)實(shí)現(xiàn)

字典樹(shù)字母的存放有26個(gè),也就是說(shuō)在實(shí)現(xiàn)的過(guò)程中,每一個(gè)節(jié)點(diǎn)的分支都有26個(gè)槽位用來(lái)存放可能出現(xiàn)的字母組合。同理如果是數(shù)字樹(shù)的話就是10個(gè)數(shù)字的組合,每個(gè)字典樹(shù)上的節(jié)點(diǎn)對(duì)應(yīng)的分支則有10個(gè)操作存放可能出現(xiàn)組合的數(shù)字。

接下來(lái)我們就基于 Java 語(yǔ)言實(shí)現(xiàn)一個(gè)字典樹(shù)的存放和遍歷索引的功能。

  • 源碼地址:https://github.com/fuzhengwei/java-algorithms
  • 本章源碼:https://github.com/fuzhengwei/java-algorithms/tree/main/data-structures/src/main/java/stack

1. 樹(shù)枝節(jié)點(diǎn)

public class TrieNode {

/** 形成一個(gè)鏈 */
public TrieNode[] slot = new TrieNode[26];

/** 字母 */
public char c;

/** 單詞:數(shù)量 > 0 表示一個(gè)單詞 */
public boolean isWord;

/** 前綴 */
public int prefix;

/** 單詞:具體的一個(gè)單詞字符串 */
public String word;

/** 解釋:?jiǎn)卧~的注釋說(shuō)明 */
public String explain;

}

字典的樹(shù)的節(jié)點(diǎn)需要包括此節(jié)點(diǎn)內(nèi)嵌的關(guān)聯(lián)節(jié)點(diǎn),之后是節(jié)點(diǎn)的字母、到此字母是否為單詞、單詞的前綴、單詞字符串和當(dāng)前單詞的非必要注釋。

2. 插入元素

圖片

public void insert(String words, String explain) {
TrieNode root = wordsTree;
char[] chars = words.toCharArray();
for (char c : chars) {
int idx = c - 'a'; // - a 從 0 開(kāi)始,參考 ASCII 碼表
if (root.slot[idx] == null) {
root.slot[idx] = new TrieNode();
}
root = root.slot[idx];
root.c = c;
root.prefix++;
}
root.explain = explain; // 單詞的注釋說(shuō)明信息
root.isWord = true; // 循環(huán)拆解單詞后標(biāo)記
}

insert 方法接收單詞和注釋信息,并對(duì)一個(gè)單詞按照 char 進(jìn)行拆分,拆分后則計(jì)算出索引位置并以此存放。存放完成后標(biāo)記單詞和附屬上單詞的注釋信息。

3. 索引元素

圖片

public List<String> searchPrefix(String prefix) {
TrieNode root = wordsTree;
char[] chars = prefix.toCharArray();
StringBuilder cache = new StringBuilder();
// 精準(zhǔn)匹配:根據(jù)前置精準(zhǔn)查找
for (char c : chars) {
int idx = c - 'a';
// 匹配為空
if (idx > root.slot.length || idx < 0 || root.slot[idx] == null) {
return Collections.emptyList();
}
cache.append(c);
root = root.slot[idx];
}
// 模糊匹配:根據(jù)前綴的最后一個(gè)單詞,遞歸遍歷所有的單詞
ArrayList<String> list = new ArrayList<>();
if (root.prefix != 0) {
for (int i = 0; i < root.slot.length; i++) {
if (root.slot[i] != null) {
char c = (char) (i + 'a');
collect(root.slot[i], String.valueOf(cache) + c, list, 15);
if (list.size() >= 15) {
return list;
}
}
}
}
return list;
}

protected void collect(TrieNode trieNode, String pre, List<String> queue, int resultLimit) {
// 找到單詞
if (trieNode.isWord) {
trieNode.word = pre;
// 保存檢索到的單詞到 queue
queue.add(trieNode.word + " -> " + trieNode.explain);
if (queue.size() >= resultLimit) {
return;
}
}
// 遞歸調(diào)用,查找單詞
for (int i = 0; i < trieNode.slot.length; i++) {
char c = (char) ('a' + i);
if (trieNode.slot[i] != null) {
collect(trieNode.slot[i], pre + c, queue, resultLimit);
}
}
}

從字典樹(shù)從檢索元素的過(guò)程分為2部分,第1部分是根據(jù)提供的索引前綴精準(zhǔn)匹配到單詞信息,第2部分是根據(jù)索引前綴的最后一個(gè)單詞開(kāi)始,循環(huán)遞歸遍歷從當(dāng)前位置所能關(guān)聯(lián)到的字母直至判斷為是單詞標(biāo)記為結(jié)束,通過(guò)這樣的方式把所有匹配動(dòng)的單詞索引出來(lái)。

list.size() >= 15 是判定索引的最大長(zhǎng)度,超過(guò)這個(gè)數(shù)量就停止索引了,畢竟這是一種O(n)時(shí)間復(fù)雜度的操作,如果加載數(shù)十萬(wàn)單詞進(jìn)行匹配,執(zhí)行速度還是比較耗時(shí)的。

四、字典樹(shù)功能測(cè)試

@Test
public void test_trie() {
Trie trie = new Trie();
// 存入
trie.insert("bat","大廠");
trie.insert("batch", "批量");
trie.insert("bitch", "彪子");
trie.insert("battle", "戰(zhàn)斗");
logger.info(trie.toString());
// 檢索
List<String> trieNodes = trie.searchPrefix("ba");
logger.info("測(cè)試結(jié)果:{}", JSON.toJSONString(trieNodes));
}

這里提供一些有相近字母的單詞和名詞,用于測(cè)試。你也可以嘗試讀取txt文件,檢索存入數(shù)十萬(wàn)單詞進(jìn)行檢索驗(yàn)證。

測(cè)試結(jié)果

06:21:38.226 [main] INFO trie.__test__.TrieTest - 測(cè)試結(jié)果:["bat -> 大廠","batch -> 批量","battle -> 戰(zhàn)斗"]

Process finished with exit code 0

通過(guò)測(cè)試結(jié)果可以看到,把所有以ba開(kāi)頭的單詞全部檢索出來(lái)了。這也是字典樹(shù)最核心功能的體現(xiàn)。

讀者在學(xué)習(xí)的過(guò)程中,可以嘗試在檢索的方法體內(nèi)打一些斷點(diǎn)看一下具體的執(zhí)行過(guò)程,方便學(xué)習(xí)整個(gè)執(zhí)行步驟。

責(zé)任編輯:武曉燕 來(lái)源: bugstack蟲(chóng)洞棧
相關(guān)推薦

2024-01-19 08:25:38

死鎖Java通信

2024-03-28 12:20:17

2023-10-13 09:04:09

2022-12-09 09:21:10

分庫(kù)分表算法

2023-08-28 07:02:10

2024-02-02 11:03:11

React數(shù)據(jù)Ref

2023-08-01 12:51:18

WebGPT機(jī)器學(xué)習(xí)模型

2024-01-02 12:05:26

Java并發(fā)編程

2023-09-06 11:31:24

MERGE用法SQL

2022-07-08 09:27:48

CSSIFC模型

2021-12-26 08:24:14

網(wǎng)關(guān)拓?fù)?/a>結(jié)構(gòu)

2024-01-11 08:21:33

Jetpack數(shù)據(jù)技術(shù)

2024-02-04 00:00:00

Effect數(shù)據(jù)組件

2023-07-26 13:11:21

ChatGPT平臺(tái)工具

2023-01-10 08:43:15

定義DDD架構(gòu)

2023-05-18 09:01:11

MBRGPT分區(qū)

2023-06-05 08:36:04

SQL函數(shù)RANK()

2023-12-07 07:03:09

2024-01-26 08:24:16

Dalvik架構(gòu)ART

2023-01-28 09:50:17

java多線程代碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩午夜| 国产精产国品一二三产区视频 | 中文字幕在线免费视频 | 一区二区三区四区在线视频 | 亚洲一区播放 | 久久婷婷色 | 欧美日韩国产高清视频 | 亚洲电影免费 | 久久久久久网站 | 亚洲福利av| 波多野吉衣久久 | 91社区视频 | 国产精品久久久久久久久久免费看 | 91精品国产综合久久久动漫日韩 | 97av在线| 99久久婷婷国产综合精品电影 | 免费观看的av| 国产99久久精品 | 国产露脸对白88av | 男人天堂久久久 | 国产精品免费一区二区三区四区 | 久久久精品一区二区 | 国产色网 | 99国产精品视频免费观看一公开 | 一区二区国产在线观看 | 精品国产免费人成在线观看 | 精品日本久久久久久久久久 | 91精品一区 | 久久久久久综合 | 国产精品免费在线 | 国产美女久久久 | 一区二区三区在线观看视频 | 日韩在线免费 | 在线资源视频 | 日本粉嫩一区二区三区视频 | 国产日韩欧美91 | 久久免费视频网 | 久久久夜| 国产亚洲一区二区三区 | 国产精品久久久乱弄 | 国产色|