字典树原理详解及其Python实现
一、原理详解
1、初步介绍:
字典树又名前缀树,Trie树,是一种存储大量字符串的树形数据结构,经常被搜索引擎系统用于文本词频统计。
除此之外也常用于计算左右信息熵、计算点互信息。
下图演示了一个保存了8个单词的字典树的结构,8个单词分别是:“A”, “to”, “tea”, “ted”, “ten”, “i”, “in”, “inn”。
2、优势:
利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率高。
相比于HashMap存储,在存储单词(和语种无关,任意语言都可以)的场景上,节省了大量的内存空间。
3、基本性质:
(1)、根节点不包含字符,除根节点外每一个节点都只包含一个字符;
(2)、从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
(3)、每个节点的所有子节点包含的字符都不相同。
二、python实现
1、创建字典树的节点
class TrieNode:def __init__(self):self.nodes = dict() # 构建字典self.is_leaf = False
2、实现插入操作
def insert(self, word: str): curr = selffor char in word:if char not in curr.nodes:curr.nodes[char] = TrieNode()curr = curr.nodes[char]curr.is_leaf = True
3、实现查找操作
def search(self, word: str):curr = selffor char in word:if char not in curr.nodes:return Falsecurr = curr.nodes[char]return curr.is_leaf
4、完整代码:
完整代码参考自:https://blog.csdn.net/danengbinggan33/article/details/82151220
# -*- coding:utf-8 -*-
"""
Description:大变双向字典树
迭代次数默认最大999,可以增加但是没必要。其实能深到999层,那这个序列还是选择另外的处理方式吧。@author: WangLeAi
@date: 2018/8/15
"""class TrieNode(object):def __init__(self, value=None, count=0, parent=None):# 值self.value = value# 频数统计self.count = count# 父结点self.parent = parent# 子节点,{value:TrieNode}self.children = {}class Trie(object):def __init__(self):# 创建空的根节点self.root = TrieNode()def insert(self, sequence):"""基操,插入一个序列:param sequence: 列表:return:"""cur_node = self.rootfor item in sequence:if item not in cur_node.children:# 插入结点child = TrieNode(value=item, count=1, parent=cur_node)cur_node.children[item] = childcur_node = childelse:# 更新结点cur_node = cur_node.children[item]cur_node.count += 1def search(self, sequence):"""基操,查询是否存在完整序列:param sequence: 列表:return:"""cur_node = self.rootmark = Truefor item in sequence:if item not in cur_node.children:mark = Falsebreakelse:cur_node = cur_node.children[item]# 如果还有子结点,说明序列并非完整if cur_node.children:mark = Falsereturn markdef delete(self, sequence):"""基操,删除序列,准确来说是减少计数:param sequence: 列表:return:"""mark = Falseif self.search(sequence):mark = Truecur_node = self.rootfor item in sequence:cur_node.children[item].count -= 1if cur_node.children[item].count == 0:cur_node.children.pop(item)breakelse:cur_node = cur_node.children[item]return markdef search_part(self, sequence, prefix, suffix, start_node=None):"""递归查找子序列,返回前缀和后缀结点此处简化操作,仅返回一位前后缀的内容与频数:param sequence: 列表:param prefix: 前缀字典,初始传入空字典:param suffix: 后缀字典,初始传入空字典:param start_node: 起始结点,用于子树的查询:return:"""if start_node:cur_node = start_nodeprefix_node = start_node.parentelse:cur_node = self.rootprefix_node = self.rootmark = True# 必须从第一个结点开始对比for i in range(len(sequence)):if i == 0:if sequence[i] != cur_node.value:for child_node in cur_node.children.values():self.search_part(sequence, prefix, suffix, child_node)mark = Falsebreakelse:if sequence[i] not in cur_node.children:for child_node in cur_node.children.values():self.search_part(sequence, prefix, suffix, child_node)mark = Falsebreakelse:cur_node = cur_node.children[sequence[i]]if mark:if prefix_node.value:# 前缀数量取序列词中最后一词的频数if prefix_node.value in prefix:prefix[prefix_node.value] += cur_node.countelse:prefix[prefix_node.value] = cur_node.countfor suffix_node in cur_node.children.values():if suffix_node.value in suffix:suffix[suffix_node.value] += suffix_node.countelse:suffix[suffix_node.value] = suffix_node.count# 即使找到一部分还需继续查找子结点for child_node in cur_node.children.values():self.search_part(sequence, prefix, suffix, child_node)if __name__ == "__main__":trie = Trie()texts = [["葬爱", "少年", "葬爱", "少年", "慕周力", "哈哈"], ["葬爱", "少年", "阿西吧"], ["烈", "烈", "风", "中"], ["忘记", "了", "爱"],["埋葬", "了", "爱"]]for text in texts:trie.insert(text)markx = trie.search(["忘记", "了", "爱"])print(markx)markx = trie.search(["忘记", "了"])print(markx)markx = trie.search(["忘记", "爱"])print(markx)markx = trie.delete(["葬爱", "少年", "王周力"])print(markx)prefixx = {}suffixx = {}trie.search_part(["葬爱", "少年"], prefixx, suffixx)print(prefixx)print(suffixx)
参考:
https://leetcode-cn.com/problems/short-encoding-of-words/solution/99-java-trie-tu-xie-gong-lue-bao-jiao-bao-hui-by-s/
https://blog.csdn.net/danengbinggan33/article/details/82151220
字典树原理详解及其Python实现相关推荐
- 视频教程-深度学习原理详解及Python代码实现-深度学习
深度学习原理详解及Python代码实现 大学教授,美国归国博士.博士生导师:人工智能公司专家顾问:长期从事人工智能.物联网.大数据研究:已发表学术论文100多篇,授权发明专利10多项 白勇 ¥88.0 ...
- google authenticator python_Google Authenticator TOTP原理详解(以Python为例)
http://xsboke.blog.51cto.com 如果有疑问,请点击此处,然后发表评论交流,作者会及时回复(也可以直接在当前文章评论). -------谢谢您的参考,如有疑问,欢迎交流 一. ...
- python google auth totp_Google Authenticator TOTP原理详解(以Python为例)
如果有疑问,请点击此处,然后发表评论交流,作者会及时回复(也可以直接在当前文章评论). -------谢谢您的参考,如有疑问,欢迎交流 一. 原理详解(图片可以点击然后放大查看) 二. 验证 1.下载 ...
- KNN算法原理详解及python代码实现
KNN算法 算法原理 对数据的要求 算法的优缺点 算法需要注意的点 算法实现(python) 算法原理 计算待测样本与train_data的距离d并保存数组中 对d进行排序,取d最近的k个样本 统计样 ...
- Xgboost算法原理详解及python实现
Xgboost算法(回归树) 1.算法原理 2.对数据的要求(无需规范化) 3.算法的优缺点 4.XGB.GBDT.LR与RF 5.python代码实现 导入相关包 读取数据并预处理 训练 贝叶斯初步 ...
- 随机森林原理详解及python代码实现
随机森林(RF)算法 1.算法原理 2.对数据的要求(无需规范化) 3.算法的优缺点 4.算法需要注意的点 5.python代码实现(待更......) 导入相关包 读取数据并预处理(必须处理缺失值) ...
- 决策树原理详解及python代码实现
决策树算法(信贷中常用来寻找规则) 1.算法原理 1.1 ID3(多叉树分类) 1.2 C4.5(多叉树分类) 1.3 Cart(二叉树分类+回归) 2.ID3.C4.5与Cart比较 3.算法优缺点 ...
- 集成经验模态(EEMD)原理详解与python实现
文章目录 1 经验模态分解(EMD) 1.1 本征模态函数(IMF) 1.2 sifting算法 1.3 原始序列重构 2 集成经验模态分解(EEMD) 2.1 EEMD算法步骤 集成经验模态分解的关 ...
- 字典树Trim详解+相关例题---龙之介算法基础课
字典树,顾名思义,是关于"字典"的一棵树. 即:它是对于字典的一种存储方式(所以是一种数据结构而不是算法). 这个词典中的每个"单词"就是从根节点出发一直到某一 ...
最新文章
- access9磅字体是多_第一套考试题
- STL中用erase()方法遍历删除元素
- 渲染到ui_虚幻4渲染编程(UI篇)【第二卷:程序化UI特效-[1]】
- 【必须收藏】那些酷炫的深度学习网络图怎么画出来的?
- 程序员怎么面试求职?需要注意哪些因素?
- MyBatis中多表查询(业务代码方式)
- edge浏览器下载位置设置
- 即将步入2020年,程序员如何在新的一年更进一步?你需要这样做
- 五分钟没有操作自动退出_消防设施操作员 精选练习题10.31
- 2018年最新Spring Boot视频教程附代码笔记资料(50G)
- 随想录(构建自己的代码库)
- ​​​​​​​微信、Facebook牵手合作,抗击全球新冠肺炎疫情
- 马云生气了 mysql_“马云生气了”之增删改查
- mysql数据导入导出 CSV格式_mysql数据一键导出到csv文件
- java 多列 统计_java – 如何计算多列(colspan)HTML表的宽度?
- 【一天一个C++小知识】009.C++面向对象
- html框架 book,HTML框架的基本结构的.doc
- 省会、自治区、直辖市、特别行政区
- 无法使用计算机名访问共享,局域网内无法用计算机名访问共享的解决办法
- 自然人机交互到底“自然”在哪儿?