第 0 个 Project 名为 C++ Primer,目标是实现一个字典树(Trie),内容不难,主要是测试参与者的 Modern C++ 编程水平,对于选课的 CMU 学生如果感觉比较吃力可能就要劝退了。

Project 说明:Project #0 - C++ Primer

本节要实现的内容全部在 src/include/primer/p0_trie.h 文件中。

字典树(Trie)是一种有序的树形结构,能够存储键值对并高效地进行前缀匹配,详细介绍可以自行百度。例如插入两个键值对 ("ab", 1)("ac", "val"),则形成下图的结构:

root 是根节点,不存储键;a 是一个非终结节点,只存储键;下层的两个节点是终结节点,除了键还要存储一个任意类型的值。每个节点有一个 map 存储以每个子节点的键索引的子节点。本节相应做出了如下设计:

TrieNode 表示非终结节点,成员为键,是否是终结节点的标记,子节点 map。TrieNodeWithValue 继承前者,表示终结节点,带有一个 T 类型的 value。二者可以通过 TrieNode 类中 is_end_ 标识区分。Trie 类表示整个 Trie 树。

TrieNode 的子节点 map 存储的是子节点的智能指针 unique_ptr<TrieNode> 而非裸指针。


注意:本节是在头文件中写代码,不要图方便写 using namespace std

TrieNode 实现

构造函数

需要注意的是移动构造函数(move constructor),由于 unique_ptr 表示独占性资源,没有拷贝构造函数,所以这里我们要用 std::movekey_char_is_end_ 是简单的内置类型(primitive type),没必要使用 move 构造。

如果不理解为什么 T&& 参数需要 move,可以参考 这个回答 或我之前的这篇博客《Effective Modern C++》学习笔记 - Item 23: 理解 std::move 和 std::forward。

InsertChildNode() 和 GetChildNode()

注意因为 unique_ptr 是独占性指针不能拷贝,返回值是 unique_ptr 的指针。


TrieNodeWithValue

构造函数

先调用基类的构造函数,is_end_ 是基类成员不能放在初始化列表中,放在函数体中赋值即可。

Trie

Trie 树的主类,这里要求实现的是增 Insert()、删 Remove()、查(GetValue) 三个函数。关于 lock_ 下面会说明。

Insert()

沿 Trie 树搜索到键的最后一个字符,过程中如果节点不存在就创建。对于最后一个键的字符分三种情况:

  1. 如果相应节点不存在,创建一个终结节点 TrieNodeWithValue,插入成功;
  2. 如果相应节点存在但不是终结节点(通过 is_end_ 判断),将其转化为 TrieNodeWithValue 并把值赋给该节点,该操作不破坏以该键为前缀的后续其它节点(children_ 不变),插入成功;
  3. 如果相应节点存在且是终结节点,说明该键在 Trie 树存在,规定不能覆盖已存在的值,返回插入失败。

Remove()

先沿 Trie 树逐字符向下搜索给定键,如果中途发现不存在直接返回 false。找到后,将该节点的 is_end_ 标为 false(此时虽然其值仍存在,但会被我们视为非终结节点)。如果该节点没有子节点,则可以删除。相应地还要向上回溯,如果其 parent 节点在移除该子节点后没有其它子节点,也删除。显然该函数可以有递归和非递归两种实现方式,我这里用非递归方式,在向下搜索时记录路径,回溯时反向遍历。因为使用智能指针,无需手动 delete 删除的 TrieNode

GetValue()

沿 Trie 树查找,如果键不存在,或者节点中存储的值类型与函数调用的类型 T 不一致,将 *success 标识设为 false。类型判断的方式是使用 dynamic_cast

并发访问(Concurrency)

要求 Trie 树能够并发访问,因此要加锁,具体也比较简单:GetValue() 时加读锁,Insert()Remove 时加写锁。项目已经提供了一个读写锁类 RWLatch,创建一个 private 成员 lock_ 放在 Trie 中,上面代码也展示了加锁解锁的操作。注意解锁要覆盖所有执行路径。

测试

test/primer/starter_trie_test.cpp 文件中 TEST() 包围的测试的名称的 DISABLED_ 前缀去除,然后编译并运行测试:

cd build
make starter_trie_test
./test/starter_trie_test

看到如下输出说明通过所有测试:

运行代码格式化和规范检查:

make format
make check-lint
make check-clang-tidy-p0

必须改正所有提示,负责后续提交评分为 0。运行:

zip project0-submission.zip \src/include/primer/p0_trie.h

生成压缩包,登录 GradeScope 并提交至 Project 0,得到以下结果则为完美通关~

【CMU15-445数据库】bustub Project #0:Trie 树实现(C++ Primer)相关推荐

  1. 0x16.基本数据结构 — Trie树(字典树)+ A C 自 动 机

    目录 用TrieTrieTrie树来处理整数异或问题是真的舒服! 一.TrieTrieTrie树 TrieTrieTrie的基本操作 0.初始化 1.插入 2.检索 二.TrieTrieTrie树例题 ...

  2. HDU1251 统计难题 【trie树】

    统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others) Total Subm ...

  3. hdu 1251 统计难题 (Trie树)

    本题是trie树模板题,如果不用trie而用map写可以看出trie处理这类问题有明显的时间优势. 在trie树中查找一个关键字的时间和树中包含的结点数无关,而取决于组成关键字的字符数.(对比:二叉查 ...

  4. c语言 trie树,C语言实现Trie树(字典树)的插入查找删除与遍历操作

    Trie树,也称作是字典树,是一种哈希树的变种,查询效率较高.Trie树可以用于统计或者排序大量的字符串,比如对一系列字符串按照字典序排序. 字典树是一个多叉树,每一个节点上存储的不是一个字符串,而是 ...

  5. 浅谈树形结构的特性和应用(上):多叉树,红黑树,堆,Trie树,B树,B+树......

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 上篇文章我们主要介绍了线性数据结构,本篇233酱带大家看看 无所不 ...

  6. 敏感词过滤,PHP实现的Trie树

    [转载]敏感词过滤,PHP实现的Trie树 原文地址:http://blog.11034.org/2012-07/trie_in_php.html 项目需求,要做敏感词过滤,对于敏感词本身就是一个CR ...

  7. Trie树:应用于统计和排序

    1. 什么是trie树 1.Trie树 (特例结构树)       Trie树,又称单词查找树.字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树结构.典型应用是用于统计和排序大量 ...

  8. 数据结构与算法之美笔记——基础篇(下):图、字符串匹配算法(BF 算法和 RK 算法、BM 算法和 KMP 算法 、Trie 树和 AC 自动机)

    图 如何存储微博.微信等社交网络中的好友关系?图.实际上,涉及图的算法有很多,也非常复杂,比如图的搜索.最短路径.最小生成树.二分图等等.我们今天聚焦在图存储这一方面,后面会分好几节来依次讲解图相关的 ...

  9. mysql索引用trie树_数据结构与算法之美【完整版】

    资源目录: ├─01-开篇词 (1讲) │ ├─00丨开篇词丨从今天起,跨过"数据结构与算法"这道坎.html │ ├─00丨开篇词丨从今天起,跨过"数据结构与算法&qu ...

最新文章

  1. cifar-10 cnn 分类
  2. linux 截取后缀名,Shell 截取文件名和后缀
  3. activeMQ相关配置与相关知识
  4. 设计模式笔记——Bridge
  5. grafana mysql插件_grafana插件动态数据
  6. DB服务器中的参数优化
  7. Spark SQL External DataSource外部数据源操作流程
  8. 7 vsphere 分配许可_外企公司员工Office 365权限是否已分配
  9. opengles图像处理之边缘检测
  10. 二进制、十进制、八进制、十六进制转换方法
  11. recover 没有捕获异常_Golang学习笔记之错误处理error、panic (抛出错误),recover(捕获错误...
  12. JZOJ100047. 【NOIP2017提高A组模拟7.14】基因变异
  13. 设计一个算法,借助栈实现单链表链接顺序的逆转
  14. 不是家电品牌!不是家装品牌!不是家居品牌!三翼鸟是啥?
  15. sql(Mysql)查询出时间数据在显示时加上时区
  16. Petalinux-conifg 错误失败
  17. 使用这个算法我可以实现英雄联盟里英雄的走位|Java 开发实战
  18. 2.Prometheus读书笔记:深入Prometheus设计
  19. access h3c交换机光口_H3C交换机的端口配置
  20. 删除链表的结点——《剑指offer》

热门文章

  1. Cocos 引擎助力游戏开发者突围
  2. WordPress如何调用其他网站的最新文章
  3. 多种在线地图综合对比,Google,必应,arcgis Online...
  4. 数据平台的基本功能是什么_如何搭建数据分析平台
  5. pingpong 攻防世界
  6. centos下面,解压.gar.gz文件
  7. C++的sort函数对于vector排序
  8. 5 Pandas数据库
  9. 南京和上海找工作的区别
  10. LuaBind --最强大的Lua C++ Bind