个人拙见,有错误请见谅
# coding=utf-8
class Node(object):
def __init__(self, value) -> None: ###约定用值为None表示节点不对应词语
self._children = {}
self._value = value
def _add_child(self, char, value, overwrite=False):
child = self._children.get(char) ###字典get()方法未查询到值时,返回None;或者默认的值
if child is None:
child = Node(value)
self._children[char] = child
elif overwrite:
child._value = value
return child
class Trie(Node):
def __init__(self) -> None:
super().__init__(None)
def __contains__(self, key):
return self[key] is not None
def __getitem__(self, key):
state = self
for char in key:
state = state._children.get(char)
if state is None:
return None
return state._value
def __setitem__(self, key, value):
state = self
for i, char in enumerate(key):
if i < len(key) - 1:
state = state._add_child(char, None, False)
else:
state = state._add_child(char, value, True)
if __name__ == '__main__':
trie = Trie()
# 增
trie['自然'] = 'nature'
trie['自然人'] = 'human'
trie['自然语言'] = 'language'
trie['自语'] = 'talk to oneself'
trie['入门'] = 'introduction'
assert '自然' in trie
# 删
trie['自然'] = None
assert '自然' not in trie
# 改
trie['自然语言'] = 'human language'
assert trie['自然语言'] == 'human language'
# 查
assert trie['入门'] == 'introduction'
执行trie['自然'] = 'nature'
结果:
首先,由trie[‘自然’] = 'nature’跳转到trie类中的__setitem__类方法中(注:当给字典变量赋值时,会自动执行内置的__setitem__方法。因为字典有内置的一些方法,执行dir(dic)
语句可查看,其中dic为设置的字典变量名称)。
然后,在for i, char in enumerate(key):
语句中,当i=0、char=‘自’时,执行if i < len(key) - 1:
条件:为trie创建一个key为’自’,value为node()的一个字典数据(其中node中self._children = {}、self._value = None)。
接着当i=1、char='然’时,执行else:
条件:可以把trie[‘自然’] = 'nature’中的value=‘nature’通过state._add_child(char, value, True)
中的_add_child方法又创建一个子节点node:key‘然’对于的value为nature。
总的流程,如下图
首先为’自’创建的node为空,当为’然’创建node1后。一开始’自’为空的node就变成了一个字典:key为’然’,value为node1。