js实现字典树

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

 

转载于:https://www.cnblogs.com/panyujun/p/11098589.html

<think>嗯,用户想了解如何用数组实现字典树(Trie)。首先,我需要回忆一下字典树的基本结构。字典树是一种树形结构,每个节点代表一个字符,从根到某个节点的路径表示一个字符串。通常每个节点会有多个子节点,对应不同的字符。传统实现可能用哈希表或指针来管理子节点,但用数组的话,可能会有不同的方法。 接下来,用户提到的是数组实现,所以应该考虑如何用数组来替代动态的子节点结构。数组的大小通常是固定的,所以每个节点需要预先确定子节点的数量。例如,如果只处理小写字母,每个节点可以有一个长度为26的数组,每个位置对应一个字母。这样,查找子节点时可以直接通过索引访问,而不需要哈希查找,提高效率。 然后,我需要考虑节点的结构。每个数组实现的Trie节点可能需要包含一个子节点数组和一个标记是否为单词结尾的布尔值。例如,在Java中,可以用一个TrieNode类,其中children是一个长度为26的数组,初始时都为null,当插入字符时,创建新的节点并放入对应的位置。 接下来,示例代码部分。需要展示如何用数组实现插入、搜索和前缀查找。比如,插入操作从根节点开始,逐个字符检查对应的索引位置是否存在节点,不存在则创建。搜索操作类似,但最后需要检查是否是单词结尾。前缀检查则只需确认路径存在即可。 可能的问题点包括数组的大小管理,比如处理大小写字母或其他字符的情况,这里示例可能只处理小写字母,所以数组大小固定为26。另外,内存占用方面,数组实现可能在空间上不如动态结构灵活,但访问速度更快。 然后,参考用户提供的引用,引用[1]提到Java实现Trie,引用[2]提到C++代码,引用[3]和[4]解释字典树的逻辑和优点,引用[5]是JavaScript实现。虽然用户提供的引用中有不同语言的例子,但用户的问题是关于数组实现的,所以需要结合这些信息,但重点在数组结构上。 最后,生成相关问题时要围绕数组实现的优缺点、优化、多语言实现和应用场景。比如,数组实现的优缺点可能涉及速度和空间,优化可能包括压缩或动态数组调整,多语言实现可以对比不同语言中数组的使用差异,应用场景则和常规Trie类似,但可能更适合固定字符集的情况。</think>### 数组实现字典树(Trie)的方法 字典树(Trie)通过数组实现的核心在于**用固定长度的数组替代指针或哈希表存储子节点**,通常适用于字符范围明确(如小写字母、数字)的场景。以下是实现细节和示例代码: --- #### **1. 数据结构设计** - **节点结构**:每个节点包含一个子节点数组和一个标记词尾的布尔值。 - 若字符集为小写字母,则数组长度为26(对应`a-z`)。 - 例如:`children[0]`对应字母`a`,`children[1]`对应`b`,依此类推。 ```java class TrieNode { TrieNode[] children = new TrieNode[26]; // 子节点数组 boolean isEnd; // 标记是否为单词结尾 } ``` --- #### **2. 核心操作实现** ##### **插入操作** ```java public void insert(String word) { TrieNode node = root; for (char c : word.toCharArray()) { int index = c - 'a'; // 计算字符对应的数组索引 if (node.children[index] == null) { node.children[index] = new TrieNode(); } node = node.children[index]; } node.isEnd = true; // 标记单词结尾 } ``` ##### **搜索操作** ```java public boolean search(String word) { TrieNode node = searchPrefix(word); return node != null && node.isEnd; // 必须为词尾 } private TrieNode searchPrefix(String prefix) { TrieNode node = root; for (char c : prefix.toCharArray()) { int index = c - 'a'; if (node.children[index] == null) { return null; } node = node.children[index]; } return node; } ``` ##### **前缀匹配检查** ```java public boolean startsWith(String prefix) { return searchPrefix(prefix) != null; // 只需路径存在 } ``` --- #### **3. 复杂度分析** - **时间复杂度**:插入、查询、前缀匹配均为$O(L)$($L$为字符串长度)。 - **空间复杂度**:$O(N \cdot C)$,其中$N$为节点数,$C$为字符集大小(如26)[^3]。 --- #### **4. 优缺点对比** | **优点** | **缺点** | |-----------------------------|------------------------------| | 访问速度快(直接索引定位) | 空间占用较高(固定长度数组) | | 避免哈希冲突 | 仅适用于固定字符集场景 | --- #### **5. 应用场景** - 敏感词过滤(快速匹配关键词前缀) - 输入法自动补全(前缀匹配) - 海量字符串的字典存储[^4] --- ### 示例代码(Java完整实现) ```java class Trie { private TrieNode root; public Trie() { root = new TrieNode(); } static class TrieNode { TrieNode[] children = new TrieNode[26]; boolean isEnd; } public void insert(String word) { TrieNode node = root; for (char c : word.toCharArray()) { int index = c - 'a'; if (node.children[index] == null) { node.children[index] = new TrieNode(); } node = node.children[index]; } node.isEnd = true; } public boolean search(String word) { TrieNode node = searchPrefix(word); return node != null && node.isEnd; } public boolean startsWith(String prefix) { return searchPrefix(prefix) != null; } private TrieNode searchPrefix(String prefix) { TrieNode node = root; for (char c : prefix.toCharArray()) { int index = c - 'a'; if (node.children[index] == null) { return null; } node = node.children[index]; } return node; } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值