前缀树
基本概念
什么是前缀树?
前缀树(Trie)又叫字典树,是一种树形的数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。
前缀树和普通的数有点区别,需要一个字段表示,是否已经结束
普通树的结点的定义:
class TreeNode {
val: any;
children: TreeNode[];
}
前缀树结点的定义:
class TreeNode {
isEnd: boolean; // 表示该结点是否是一个串的结束
children: { [key: string]: any }; // 孩子用对象表示,用当前字符作为对象的key
}
前缀树张什么样子?
假设有3个字符串about、and、apple构建成一棵前缀树
构建起来就是这样的
思路
知道了前缀树的构成,代码写起来就很清晰
- 插入:声明一个指针
node,遍历要插入的字符串,看当前字符是否在当前节点中存在,不存在则创建一个新节点,然后将指针指向这个新节点,遍历完成后,给指针指向的最后一个节点加上属性node.isEnd = ture - 查找:遍历这个字符串,每个字符都看看在前缀树中存不存在,不存在直接返回
false,存在并且遍历到最后有isEnd标识结束则为找到,返回true - 前缀查找:流程和查找一样,但有无
isEnd标识都行
代码
class Trie {
children: { [key: string]: any };
constructor() {
this.children = {};
}
/**
* 向前缀树中插入当前字符串
**/
insert(word: string): void {
let node = this.children;
for (const ch of word) {
if (!node[ch]) {
node[ch] = {}; // 如果字符不存在,创建一个新的节点
}
node = node[ch]; // 指向下一个字符
}
node.isEnd = true; // 标识当前字符串已结束
}
/**
* 查看前缀树中是否含有目标字符串作为前缀
**/
serachPrefix(word: string): { [key: string]: any } | false {
let node = this.children;
for (const ch of word) {
if (!node[ch]) {
return false; // 找不到当前字符,直接返回false
}
node = node[ch]; // 指向下一个字符
}
return node; // 返回字符串最后一个字符对应的节点
}
/**
* 查看前缀树中包含要查找的目标字符串
**/
search(word: string): boolean {
const node = this.serachPrefix(word);
return node && !!node.isEnd; // 最后一个节点存在并且有结束标识
}
/**
* 查看前缀树中是否含有目标字符串作为前缀
**/
startsWith(prefix: string): boolean {
return this.serachPrefix(prefix) as boolean; // 最后一个节点存在,不管有没有结束标识
}
}