Python实现字典树-Trie

本篇文章将解释什么是字典树以及字典树的Python实现

  • 什么是字典树(Trie)
    • 节点设计
    • 数据结构设计
    • 实现

什么是字典树(Trie)

字典树是一种树型数据结构,通常用来存储大量字符串。字典树的每个节点通常都为一个字符。从根节点的第一个孩子节点开始到可以作为字符串结尾的节点的路径就是Trie所存储的字符串,这种存储方式带来的好处就是Trie的时间复杂度和存储字符串的数据量无关只与查询的字符串长度有关,这也是字典树存在的主要意义之一。
下面以存储单词为例实现一颗字典树,实际上Python中字典是动态数据结构理论上是不会限制字典树支持的字符种类,但在一些静态语言中可能需要额外注意开辟多大的字典空间

节点设计

  1. Trie的节点无需存储节点代表的字符串,只需要存储节点是否是某一字符串的结尾;
  2. Trie要存储孩子节点的信息,这里采用字典进行存储,也就是说'在访问到孩子节点的时候就可以确定孩子节点所代表的字符',所以字典树不用存储字符本身;
class Node(object):
    def __init__(self, is_word = False):
    	# True 表示这个节点是一个字符串的结尾
        self.is_word = is_word
        # node key 中存储着孩子节点代表的字符 value 中存储着孩子节点的指针
        self.node = {}

数据结构设计

  1. def add(word) // return None 向Trie中添加一个单词
  2. def contains(word) // return bool 询问Trie是否包含word
  3. def is_prefix(prefix) // return bool 询问字典树是否包含该前缀的单词
  4. def size() // ruturn int 返回字典树存储单词个数

实现

class Node(object):
    def __init__(self, is_word = False):
        self.is_word = is_word
        self.node = {}

# 为了保证数据结构的Python风格,有些功能采用魔法函数实现
class Trie(object):

    def __init__(self):

        self.size = 0
        self.root = Node()
        
    def __len__(self):
        return self.size

    def add(self, word):

        cur = self.root

        for char in word:
            if cur.node.get(char) is None:
                cur.node[char] = Node()

            cur = cur.node[char]

        if not cur.is_word:
            cur.is_word = True
            self.size += 1

    def add_by_recursion(self, word):
        self.__add(word, 0, self.root)

    def __add(self, word, i, cur):

        if i == len(word):
            if not cur.is_word:
                cur.is_word = True
                self.size += 1
            return

        if cur.node.get(word[i]) is None:
            cur.node[word[i]] = Node()

        self.__add(word, i + 1, cur.node[word[i]])

    def __contains__(self, item):

        cur = self.root

        for char in item:
            if cur.node.get(char) is None:
                return False

            cur = cur.node[char]

        return cur.is_word

    # 前缀搜索
    def is_prefix(self, prefix):
        cur = self.root

        for char in prefix:
            if cur.node.get(char) is None:
                return False
            cur = cur.node[char]

        return True

转载注明出处

你可能感兴趣的:(一起学数据结构)