35.Trie树:如何实现搜索引擎的搜索关键词提示功能?

 

他是如何实现的?底层使用的哪种数据结构和算法?

底层最基本的原理:Trie树

 

何为Trie树?

又名“字典树”,树形结构。专门处理字符串匹配的数据结构。

解决问题:在一组字符串集合中快速查找某个字符串。

举例:有6个字符串集合:how,hi,her,hello,so,see.在该集合中多次查找某个字符串是否存在。

原始方法:每次查找,待查找的字符串依次与集合中的6个字符串匹配,效率低下。

Trie方法:

本质:利用字符串之间的公共前缀,将重复的前缀合并在一起(兄弟节点按字母顺序插入,先放在左子树)。

查找he,但e节点非叶子节点,是某个字符串的前缀子串,无法匹配(若he位于字符串集合,可在节点里做好标记)。

 

 

 如何实现Trie树

class Trie(object):
    def __init__(self):
        self.root={}
        self.word_end=""
        self.list1=list()

    def insert(self,word):
        curNode=self.root
        for c in word:
            if c not in curNode:
                curNode[c]={}#一个字符作为键,指向一个空字典
            curNode=curNode[c]
        curNode[self.word_end]=True

    def search(self,word):
        curNode = self.root
        for c in word:
            if c not in curNode:
                return False
            curNode=curNode[c]
        if self.word_end not in curNode:
            return False
        return True
    def startswith(self,prefix):
        curNode = self.root
        for c in prefix:
            if c not in curNode:
                return False
            curNode=curNode[c]
        return True

t = Trie()
t.insert("ac")
t.insert("a")
t.insert("b")
print(t.search("wzc"))
print(t.startswith("a"))

"""
时间复杂度:构建树时,需要扫描所有字符串,O(n)(n为所有字符串长度和);查询时,只需要对比k个节点(k为待查询的字符串的长度),O(k)
"""

 

 

 

Trie主要有两个操作:1.将字符串构造成Trie树; 2.在Trie树中查询一个字符串

 对于多叉树,如何存储一个节点的所有子节点的指针?

下标与字符一一映射,来存储子节点的指针。

class TrieNode {
  char data;
  TrieNode children[26];#查找时,通过ASCII码-“a”的ASCII码,迅速找到子节点的指针。
}

 

 若字符仅为26个小写字符,需要26个数组,若字符更多样,占用内存更多;

解决方法:将每个节点的数组换成其他数据结构,比如有序数组、跳表、散列表、红黑树等

举例有序数组:数组中的指针根据所指向的子节点的字符大小顺序排序。查询时,可以二分查找。但插入时,为维护数组中数据的有序性,稍微慢一点。

 缩点优化:对仅有一个子节点的节点,而且此节点不是一个串的结束节点,可以将此节点与子节点合并。

 

Trie与散列表、红黑树的比较

字符串匹配问题本质上就是数据查找问题。支持动态数据高效操作的数据结构:散列表、红黑树、跳表等

在一组字符串中查找字符串,Trie表现欠佳:

  • 1.字符串包含的字符集不能太大,存储空间非常大,即使可以优化,也要付出牺牲查询、插入效率的代价;
  • 2.要求字符串前缀重合比较多;
  • 3.必须从零开始构建Trie,在工程上简单问题复杂化;
  • 4.用指针串起来的字符串,对缓存不友好;

工程上,更倾向于散列表或红黑树(编程语言提供现成库)

用武之地:对于精确匹配查找,散列表或红黑树更合适。Trie比较适合的是查找前缀匹配的字符串(搜索关键词的提示功能)。

 

解答开题

假设关键词库由用户的热门搜索关键词组成,构造Trie树。当输入某个词时,把这个词作为一个前缀子串在Trie中匹配。

Trie树的扩展运用:自动补全(代码编辑器自动补全、输入法自动补全等)

小结

对内存不敏感或内存消耗在可接受范围的,Trie的字符串匹配还是十分高效的

 

posted on 2019-03-02 11:43  wzc521  阅读(124)  评论(0)    收藏  举报

导航