CMU14445
Task #1 - Copy-On-Write Trie
-
Get()思路:
获取根节点指针,顺着key
逐字符往下找节点,最后根据题意可以使用dynamic_cast
检查是否是TrieNodeWithValue(dynamic_pointer_cast也可以)
,以下为两者用法:auto value_node = std::dynamic_pointer_cast<const TrieNodeWithValue<T>>(cur)); auto value_node = dynamic_cast<const TrieNodeWithValue<T>*>(cur.get())
-
Put()思路:
1)若Trie
是空,先创建新节点作为根节点,否则,克隆根节点。
2)若key
为空,根节点转化为TrieNodeWithValue
后返回。
3)指针cur
指向原Trie
以便顺着key
逐字符往下找节点,指针ret_prev,ret_cur,ret_next
分别用于指向上一个节点,当前节点,下一个节点。ret_next
为cur
下一个节点的克隆,随后修改ret_cur
的对于字符索引为ret_next
。
4)key
处理完后,通过ret_prev
和ret_cur
处理最后的节点,即通过ret_cur
构造TrieNodeWithValue
节点挂在ret_prev
上即可。 -
Remove()思路:
1)若Trie
是空,直接返回空Trie
。
2)顺着key
逐字符向下找路径,用栈记录,栈中元素为即为map
对应的键和值。
3)此时,从栈顶到栈底的顺序即为key
路径节点的逆序,其中栈底对应根节点。先将key
对应的节点TrieNodeWithValue
替换为TrieNode
。
4)若是key
是空,则直接将根节点TrieNodeWithValue
替换为TrieNode
返回。
5)若是key
对应的节点没有分支,则通过栈回溯路径节点,该删的删,一旦删不了就break
。
6)若栈空且根节点无分支就说明Trie
删成了空,返回空Trie
,否则不断出栈,获取根节点并返回。
Task #2 - Concurrent Key-Value Store
没啥难度,仔细读题,理解题意即可,需要注意Trie.Put()
并不是在原Trie
上添加,而是返回一个新的Trie
。加锁和解锁可以简单使用mutex.unlock() mutex.lock()
即可。
Task #3 - Debugging
我个人是使用Clion进行该项目的,按要求进行断点设置,查看变量即可,很快。
Task #4 - SQL String Functions
upper
和lower
按要求写就行,当时我用的时std::transform
算法来实现的,并遇到了一些问题,见此。随后在plan_func_call.cpp
中按所给注释写就行。
总结
这个project
除了Task1
刚上手有些陌生且思路不是太清晰写起来费些时间,之后几个就很快。借此,复习太久没动过的C++
,重新认识了智能指针等C++技术和特性。
所遇问题
简单记下所遇问题,希望会对你有所帮助。
-
关于项目本身,不一定是要
clone
这个项目的最新版,而是要根据你所处的学期clone
对应的版本 -
关于代码编辑器,我选择
Clion
,相比于VScode
更加便于调试和上手 -
关于编译器,项目要求是
clang
,但我这里默认是gcc g++
,可以按照下面在bustub
目录下CMakeLists.txt
的开始处添加如下两行进行设置set(CMAKE_C_COMPILER "/usr/bin/clang-14") set(CMAKE_CXX_COMPILER "/usr/bin/clang++-14")
-
关于格式化,网上找对应
google
格式clang-format
文件,复制到bustub
目录下的clang-format
文件,并确保如下设置,所若google
那个代码规格文档,说行长不过80,但一些特殊的情形除外,但clang-format
并无法识别,故在这里认为设置为120,避免上传提交时再次修改ColumnLimit: 120