python中的字典树:创建,搜索,扩展单词,打印字典树

python中的字典结构非常好用,直接利用键赋值tree[key]=value 就可以很容易的创建出树形结构的分支。

字典树经常用来代替list数据类型存储词典数据,即便词典是百万级的数量,字典树也会以很小的计算代价实现搜索。

这里使用面向函数的方法实现字典树(Trie),方便理解和粘贴。

1.创建一个字典树

方法1 直接赋值

# 创建字典方法1
Trie = {"a": "$",
        "b": {
            "c":
                {"g": "$", "h": "$"},
            "e":
                {"i": "$", "j": "$"},
            "f":
                {"k": "$", "l": "$"},
        }}

方法2 把列表转换为字典树

# 创建字典方法2
lst = ['a', 'bcg', 'bch', 'bei', 'bej', 'bfk', 'bfl']
Trie = {}

for i in lst:
    cur_node = Trie
    for x in i[:-1]:
        if x not in cur_node:
            cur_node[x] = {}
        cur_node = cur_node[x]
    cur_node[i[-1]] = '$'

打印字典树

print(Trie)

python循环字典的创建 python循环生成字典_python循环字典的创建


我们利用$作为叶节点的标志,以$为结束的路径都作为一个完整的单词,不论使用方法1还是方法2,该字典树的结构图如下

字典树结构图

python循环字典的创建 python循环生成字典_算法_02

2.在字典树中搜索单词是否存在

获得了树结构的字典,我们必然要考虑如何使用字典树,我们希望能实现红色箭头的搜索过程

字典搜索路径图

python循环字典的创建 python循环生成字典_python循环字典的创建_03

利用search方法搜索wordTrie中是否为正确的单词,搜索单词是否存在,找到单词就返回True

# 在字典树中搜索单词是否存在
def search(word):
    cur_node = Trie
    for i in word:
        try:
            cur_node = cur_node[i]
        except:
            return False
    return True if cur_node == '$' else False

调用方法

# 路径不存在于字典的情况
print(search('bce'))
# 路径不是完整的单词的情况
print(search('b'))
# 路径是合理的单词的情况
print(search('a'))
print(search('bgj'))

python循环字典的创建 python循环生成字典_python_04

3.补全单词

我们经常会遇到一种情况,我们有一个不完整的单词,我们希望在字典中找到这个以这个不完整单词开头的所有可能,对不完整的单词进行补全

单词补全路径图

红色是访问不完整单词的路径,绿色是补全的路径,通过不完整单词bg获取到补全单词bgi,bgj

python循环字典的创建 python循环生成字典_数据结构_05


get_start_with是获取到所有broken_word的补全单词,返回结果在一个列表中,get_completion_words通过递归的方式遍历传入节点处的字典

# Author:HeartMaster
# 寻找以broken_word为开头,一直到叶节点的每个路径
def get_start_with(broken_word):
    # 以字符串为路径找到最后一个字符在字典中的节点
    cur_node = Trie
    for i in broken_word:
        try:
            cur_node = cur_node[i]
        # 路径不存在字典中,则直接返回原词
        except:
        	# 搜索单词如果不存在字典树的路径中,我们直接返回这个单词
            return [broken_word]

    # 递归遍历字典树
    def get_completion_words(pre_string, cur_node):
        word_list = []
        # 叶节点退出递归,返回完整字符串
        if cur_node == '$':
            word_list.append(pre_string)
            return word_list
        # 通过字典树的每个分支对之前的字符串进行补充
        for key in list(cur_node):
            word_list.extend(get_completion_words(pre_string + str(key), cur_node[key]))
        # 返回最终结果
        return word_list

    return get_completion_words(broken_word, cur_node)

调用方法

# 字典中不存在的情况
print(get_start_with('ag'))
# 可以拓展的情况
print(get_start_with('b'))
print(get_start_with('bc'))
print(get_start_with('bfa'))
# 利用递归遍历了整个字典树
print(get_start_with(''))

我们希望这个单词不论是否可以扩展,甚至不存在于字典中,都被返回

python循环字典的创建 python循环生成字典_python循环字典的创建_06

4.遍历打印整个字典树

如果传入空字符,这个方法将遍历打印整个字典

print(get_start_with(''))

python循环字典的创建 python循环生成字典_数据结构_07