内存空间有限情况下的词频统计 Trie树 前缀树
数据结构与算法专题——第十二题 Trie树
https://mp.weixin.qq.com/s/nndr2AcECuUatXrxd3MgCg
今天来聊一聊Trie树,Trie树的名字有很多,比如字典树,前缀树等等。
一:概念
下面有and,as,at,cn,com这几个关键词,构建成 trie 树如下。
从上面图中,应该可以或多或少的发现一些好玩的特性。
- 根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
- 从根节点到某一节点,路径上经过的字符连接起来,就是该节点对应的字符串。
- 每个单词的公共前缀作为一个字符节点保存。
二:使用范围
既然学Trie树,肯定要知道这玩意是用来干嘛的?
1. 词频统计。
可能有人要说了,词频统计简单啊,一个hash或者一个堆就可以打完收工,但问题来了,如果内存有限呢?还能这么玩吗?这种限制级条件下就可以用trie树来压缩下空间,因为公共前缀都是用一个节点保存的。
2. 前缀匹配
就拿上面的图来说吧,如果我想获取所有以 "a" 开头的字符串,从图中可以很明显的看到是:and,as,at,如果不用trie树,你该怎么做呢?很显然朴素的做法时间复杂度为O(N2) ,用Trie树就不一样了,它可以做到h,h为你检索单词的长度,可以说这是秒杀的效果。
举个例子:现有一个编号为1的字符串”and“,怎样插入到trie树中呢?采用动态规划的思想,将编号”1“计入到每个途径的节点中,那么以后我们要找”a“,”an“,”and"为前缀的字符串的编号将会轻而易举。
三:实际操作
到现在为止,我想大家已经对trie树有了大概的掌握,下面看看如何来实现。
1:定义trie树节点
为了方便,我也采用纯英文字母,大家都知道字母有26个,所以构建的trie树就是一个26叉树,每个节点包含26个子节点,实现代码如下:
/// <summary>
/// Trie树节点
/// </summary>
public class TrieNode
{
/// <summary>
/// 26个字符,也就是26叉树
/// </summary>
public TrieNode[] childNodes;
/// <summary>
/// 词频统计
/// </summary>
public int freq;
/// <summary>
/// 记录该节点的字符
/// </summary>
public char nodeChar;
/// <summary>
/// 插入记录时的编码id
/// </summary>
public HashSet<int> hashSet = new HashSet<int>();
/// <summary>
/// 初始化
/// </summary>
public TrieNode()
{
childNodes = new TrieNode[26];
freq = 0;
}
}
2: 添加操作
从上面图中,应该可以或多或少的发现一些好玩的特性。
- 根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
- 从根节点到某一节点,路径上经过的字符连接起来,就是该节点对应的字符串。
- 每个单词的公共前缀作为一个字符节点保存。
二:使用范围
既然学Trie树,肯定要知道这玩意是用来干嘛的?
1. 词频统计。
可能有人要说了,词频统计简单啊,一个hash或者一个堆就可以打完收工,但问题来了,如果内存有限呢?还能这么玩吗?这种限制级条件下就可以用trie树来压缩下空间,因为公共前缀都是用一个节点保存的。
2. 前缀匹配
就拿上面的图来说吧,如果我想获取所有以 "a" 开头的字符串,从图中可以很明显的看到是:and,as,at,如果不用trie树,你该怎么做呢?很显然朴素的做法时间复杂度为O(N2) ,用Trie树就不一样了,它可以做到h,h为你检索单词的长度,可以说这是秒杀的效果。
举个例子:现有一个编号为1的字符串”and“,怎样插入到trie树中呢?采用动态规划的思想,将编号”1“计入到每个途径的节点中,那么以后我们要找”a“,”an“,”and"为前缀的字符串的编号将会轻而易举。
内存空间有限情况下的词频统计 Trie树 前缀树的更多相关文章
- 软工之词频统计器及基于sketch在大数据下的词频统计设计
目录 摘要 算法关键 红黑树 稳定排序 代码框架 .h文件: .cpp文件 频率统计器的实现 接口设计与实现 接口设计 核心功能词频统计器流程 效果 单元测试 性能分析 性能分析图 问题发现 解决方案 ...
- LeetCode 80,不使用外部空间的情况下对有序数组去重
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题的第49篇文章,我们一起来看LeetCode的第80题,有序数组去重II(Remove Duplicates fr ...
- Linux查看磁盘目录内存空间使用情况
du 显示每个文件和目录的磁盘使用空间 命令参数 -c或--total 除了显示个别目录或文件的大小外,同时也显示所有目录或文件的总和. -s或--summarize 仅显示总计,只列出最后加总的 ...
- JS如何在不给新空间的情况下给数组去重?
1.先排序,在让相邻元素对比去重 const nums = [3, 1, 1, 5, 2, 3, 4, 3, 5, 5, 6, 4, 6, 6, 6]; Array.prototype.arrayNo ...
- alloc_page分配内存空间--Linux内存管理(十七)
1 前景回顾 在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法. Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算法由Know ...
- STM32内存受限情况下摄像头驱动方式与图像裁剪的选择
1.STM32图像接收接口 使用stm32芯片,128kB RAM,512kB Rom,资源有限,接摄像头采集图像,这种情况下,内存利用制约程序设计. STM32使用DCMI接口读取摄像头,协议如下. ...
- 萌新笔记——linux下查看内存的使用情况
windows上有各种软件可以进行"一键加速"之类的操作,释放掉一些内存(虽然我暂时不知道是怎么办到的,有待后续学习).而任务管理器也可以很方便地查看各进程使用的内存情况,如下图: ...
- linux下查看内存的使用情况
windows上有各种软件可以进行“一键加速”之类的操作,释放掉一些内存(虽然我暂时不知道是怎么办到的,有待后续学习).而任务管理器也可以很方便地查看各进程使用的内存情况,如下图: 同样地,linux ...
- 简单统计SQLSERVER用户数据表大小(包括记录总数和空间占用情况)
在SQLSERVER,简单的组合sp_spaceused和sp_MSforeachtable这两个存储过程,可以方便的统计出用户数据表的大小,包括记录总数和空间占用情况,非常实用,在SqlServer ...
随机推荐
- Git提交错了不用慌,这三招帮你修改记录
大家好,今天我们来聊聊git当中一个很重要的功能--历史记录的修改. 有的时候我们会突然发现某个地方需要修改,最常见的某个不应该被提交的文件被提交了进来.我们希望它不只是在后序的版本当中不再出现,而是 ...
- jdbc编程学习(1)
一,背景 1996年,sun公司发布了第一版本的数据库连接(JDBC)API,使编程人员可以通过这个API接口连接到数据库,并使用结构化查询语言(SQL)完成对数据库的查找与更新.JDBC自此成为Ja ...
- JavaSwing 船只停靠管理可视化(一)
最近抽空闲时间做了船只停靠管理系统,先看一下效果. 停靠泊位管理:实现泊位的 增删改查. JavaSwing 船只停靠管理可视化(一) JavaSwing 船只停靠管理可视化(二) JavaSwing ...
- Spring 之AOP AspectJ切入点语法详解
记录一下,以后学习 https://blog.csdn.net/zhengchao1991/article/details/53391244
- Unity Package Manager
(注:Unity 2018.1及以后的版本才可以使用Package Manager.) 一个package是一个容器,里面放的是Assets, Shaders, Textures, plug-ins, ...
- spring boot maven profiles,打包不同的配置文件
1. 在pom.xml添加 <profiles> <profile> <id>dev</id> <properties> <envir ...
- 腾讯IOT安卓开发初探
目录 腾讯IOT 安卓开发初探 Tecent IOT 开发平台的使用 新建项目 创建产品 添加自定义功能 设备开发 微信小程序配置 面板配置 新建设备 使用设备 安卓开发 前置配置 data.json ...
- github下载大文件太慢/失败
场景 github下载大文件,使用浏览器下载zip包到本地在下载到1G时失败, 使用 git clone ssh下载速度20k/s以下,已fq. 解决方法(亲测) 1.下载Github Desktop ...
- Linux 下挂载新硬盘方法(转)
1.关闭服务器加上新硬盘 2.启动服务器,以root用户登录 3.查看硬盘信息 #fdisk -l Disk /dev/sda: 42.9 GB, 42949672960 bytes 255 ...
- 【C++】《Effective C++》第四章
第四章 设计与声明 条款18:让接口容易被正确使用,不易被误用 请记住 好的接口很容易被正确使用,不容易被误用.你应该在你的所有接口中努力达到这些性质. "促进正确使用"的办法包括 ...