Trie也可以叫做Prefix Tree(前缀树),也是一种搜索树。Trie分步骤存储数据,树中的每个节点代表一个步骤,trie常用于存储单词以便快速查找,比如实现单词的自动完成功能。 Trie中的每个节点都包含一个单词的字母,跟着树的分支可以可以拼写出一个完整的单词,每个节点还包含一个布尔值表示该节点是否是单词的最后一个字母。
1、字典树是一种树形结构,树形由root根节点和子节点组成
2、根节点是没有值的
3、从根节点的子节点开始,每个子节点存储一个字符,每个字符都不相同
4、从根节点到某节点,所形成的路径,将该路径中的所有节点的值连接起来,就是这个节点所对应的字符串
5、字典树可以用来搜索和统计,效率比hash高,是用空间换时间
6、查询和遍历都是从当前节点的子节点开始
class Treenode {
constructor(key,leaf){
this.key = key;
this.leaf = leaf;
this.count = 0;
if(!leaf){
this.children = [];
}
}
}
class Tree{
constructor(){
var root = new Treenode(null,false);
this.root = root;
}
run(strs){
var root = this.root;
for(let i=0;i<strs.length;i++){
this.insertNode(root,strs[i]);
}
}
//创建字典树
insertNode(node,str){
if(!node.leaf){
//当前节点的子节点中是否有字符串的第一个字符,从子节点中匹配
var child = node.children.find(function(child){
return child.key == str[0];
});
if(child){
//有多少单词通过这个节点,即由根至该节点组成的字符串模式出现的次数
child.count++;
//子节点中存在,则继续遍历下一个字符
this.insertNode(child,str.substring(1));
}else{
//子节点中没有,则插入该节点
if(str.length==1){
var child = new Treenode(str[0],true);
}else{
var child = new Treenode(str[0],false)
}
node.children.push(child);
this.insertNode(child,str.substring(1));
}
}
}
search(txt){
if(!txt){
return;
}
//从根节点开始查找匹配
var root = this.root;
var isIn = this.searchTxt(root,txt);
console.info(isIn);
}
searchTxt(node,txt){
if(!txt){
return false;
}
if(!node.leaf){
//判断子节点中是否有相等值
var child = node.children.find(function(child){
return child.key == txt[0];
});
if(!child){
//没有匹配到字符,说明不存在
return false;
}else if(child.leaf){
//说明已经是找到头了
return child;
}else {
if(txt.length==1){
//字符串已经匹配完,但是节点不是叶子节点,说明不存在
return false;
}
return this.searchTxt(child,txt.substring(1));
}
}else{
//查到了叶子节点,判断当前节点的值是否相等
if(node.key == txt[0]){
return node;
}else{
return false;
}
}
}
getRoot(){
return this.root;
}
}
var strs=['hello','hi','hello','hellen','red','read'];
var tree = new Tree();
tree.run(strs);
tree.search('hel');//false