Js实现Trie 字典树

1,111 阅读2分钟

js实现字典树(Trie树)

字典树,又称单词查找树、Trie树,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

image-20220222120725520

下拉框

现在,我们用js来实现一下这个数据结构。

用一个对象来表示这个树

constructor

class Trie {
    constructor() {
        this.data = {}
    }
}

insert

编写insert方法,通过isEnd属性标记一下,是不是一个完整的单词,方便后续的查询

// 插入一个单词,例如:apple
class Trie {
    constructor() {
        this.data = {}
    }
    insert(word) {
        let node = this.data
        for (let c of word) {
            if (node[c]) {
                node = node[c]
            } else {
                node[c] = {}
                node = node[c]
            }
        }
        //通过isEnd标记是否是一个完整的单词
        node['isEnd'] = true
    }
}
​
let trie=new Trie()
trie.insert('apple')
console.log(JSON.stringify(trie.data));//{"a":{"p":{"p":{"l":{"e":{"isEnd":true}}}}}}
trie.insert('acc')
//{"a":{"p":{"p":{"l":{"e":{"isEnd":true}}}},"c":{"c":{"isEnd":true}}}}
console.log(JSON.stringify(trie.data));
​

Search

编写search方法,查找trie里是否存在一个完整的单词,通过isEnd属性判断

class Trie {
    constructor() {
        this.data = {}
    }
  search(word) {
        let node = this.data;
        for (let c of word) {
            if (!node[c]) {
                //trie找不到那个字母也返回false
                return false
            }
            node = node[c]
        }
      //没有这个属性就返回fasle,有就放回true
        return !!node['isEnd'];
    }
}
​
let trie=new Trie()
trie.insert('apple')
console.log(trie.search('app'));// false
console.log(trie.search('apple'));// true

startWith

编写startWith 方法,查找trie中是否存在word的前缀,匹配则返回匹配的节点,方便后续的查找。

class Trie {
    constructor() {
        this.data = {}
    }
    startWith(word){
    let node =this.data;
    for (let c of word){
        if(!node[c]){
            return false
        }
        node=node[c]
    }
    return  node
}}
​
let trie=new Trie()
trie.insert('apple') 
console.log(trie.startWith('acc'));//false
console.log(trie.startWith('app'));//{ l: { e: { isEnd: true } } }
console.log(trie.startWith('apple'));//{ isEnd: true }

findSuffix

编写查找后续单词的方法findSuffix,

class Trie {
    constructor() {
        this.data = {}
    }
    startWith(word){
    let node =this.data;
    for (let c of word){
        if(!node[c]){
            return false
        }
        node=node[c]
    }
    return  node
}
  findSuffix(word){
      //递归查找
        function findAll(prefix,node,arr=[prefix]) {
            for (let key in node){
                if(key!=='isEnd'){
                    let word=prefix+key
                    arr.push(word)
                    findAll(word,node[key],arr)
                }
            }
            return arr;
        }
        let node=this.startWith(word)
        if(!node){
            return  false;
        }
        return findAll(word,node)
    }
}
let trie=new Trie()
trie.insert('apple')
trie.insert('appc')
console.log(trie.findSuffix('app'));//[ 'app', 'appl', 'apple', 'appc' ]

目前只有插入和查询,删除操作比较复杂,待更新