课程网站:CMU 15-445/645 : Intro to Database Systems (Fall 2022)
github:cmu-db/bustub:
cmu15445 是基于c++17 要求实现一个DBMS并且最后可以运行sql查询,再课程中Andy 也说这是可以用来在简历上写的项目,并且也可以拿到很不错的offer(但是国内写的人很多,就当一个练手的项目了,毕竟是要把基础四大件要写一遍的)
课程标准环境是:ubuntu + clang-12+ CMake(较高版本)
我的环境 ubuntu18 + clang-12 + CMake3.22.1( 之前用centos但是有bug被迫换系统))
在GitHub上安照给出的教程clone项目并编译即可,GitHub都给出的详细步骤,需要注意的是Github上是最新版本,如果想做之前版本需要找到之前的commit历史然后git 回滚一下就可以
然后在build目录测试运行test
我使用的是vscode 然后用gdb调试
"version": "0.2.0",
"configurations": [
{
"name": "bustub debug", //!挑个容易识别的名字
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/bustub-private/build/test/${fileBasenameNoExtension}", //!设置为测试程序源码相对应的目标程序路径
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
//"preLaunchTask": "C/C++: g++-8 build active file", //!不需要前置任务
"miDebuggerPath": "/usr/bin/gdb"
}
]
由于test下的测试文件初始并不是打开的,所以测试时要进入对应测试文件把DISABLE_删除
本实验是一个简单使用c++语法写一个字典树
首先实现分为三个类
原文:
TrieNode类在Trie中定义单个节点。TrieNode保存一个键的一个字符
is_end_标志表示它是否标志着一个键字符串的结束。
它的子节点存储为char到unique_ptr的映射。子节点的key字符用于访问children_map。
注意,子节点为unique_ptr意味着在将它们分配给其他变量时需要小心。
InsertChildNode和GetChildNode都返回一个指向unique_ptr的指针,这样你就可以访问unique_ptr的数据,而不需要复制或放弃所有权。
就是实现对一个结点的操作,每个结点都是有自己的key_char_然后该结点可能拥有多个叶子(存储在unordered_map里)比较简单按照注释给出的实现即可
原文:
TrieNodeWithValue类继承自TrieNode,它表示一个终端节点(节点的key_char是键的结束字符),可以保存任意类型t的值。它的is_end_标志总是为真。
当您使用给定的键遍历triendewithvalue并到达结束字符时,您将基于不同的场景为triendewithvalue调用不同的构造函数(详细信息请参见triendewithvalue一节)。现在,您只需要知道TrieNodeWithValue(char key_char, T value)构造函数用给定的键字符和值从头创建一个TrieNodeWithValue。
这个就是相当于一个结点的另一种形态用来存字典树的value的
该类是结合前俩个实现就可以了,简单的数据结构实现其中主要方法是
若key不存在创建并将叶子结点转成TrieNodeWithValue 然后存储值
若key存在但是叶子结点并不是TrieNodeWithValue那么需要把叶子结点转成TrieNodeWithValue 存储值后挂上去
若key存在但是叶子结点的is_end_ == true说明已经存在对应的key和value了,所以应该返回不要更新值
根据给定的键遍历树。如果键不存在,立即返回。
将终端节点的is_end_标志设置为false。
如果此终端节点没有任何子节点,则通过从其父节点的children_映射中删除它来删除它。
遍历整个树并递归地删除没有子节点的节点。当遇到有子节点时停止。
给定一个键,返回其对应的t类型值。如果没有找到键或提供的类型与节点的值类型不匹配,则将success设置为false。为了检查这两种类型是否相同,dynamic_cast 转换TrieNode指针为triendewithvalue 指针。如果转换结果为nullptr,则类型T与存储在节点中的值不匹配。
上述讲义上给的比较全了,按照对应一步一步写就可以了