当前位置: 首页 > news >正文

网站规划建设与管理维护教学大纲wordpress文章页添加小工具

网站规划建设与管理维护教学大纲,wordpress文章页添加小工具,网站开发需求分析,邢台做移动网站公司电话号码#xff08;最近两个月学校项目有亿点忙#xff0c;鸽得有点久#xff0c;先来把 Project 2 补上#xff09; 本节实验文档地址#xff1a;Project #2 - BTree Project 2 要实现的是数据结构课上都会讲的一个经典结构 B 树#xff0c;但是相信大多数的同学#xff08;…最近两个月学校项目有亿点忙鸽得有点久先来把 Project 2 补上 本节实验文档地址Project #2 - BTree Project 2 要实现的是数据结构课上都会讲的一个经典结构 B 树但是相信大多数的同学包括博主当时都没有自己动手实现过它本节就是一个很好的锻炼机会。 本节内容会大量使用到 Project 1 实现的 BufferPoolManager当然也包含了其内部用到的 ExtendibleHashTable 和 LRUKReplacer所以需要完成前置内容博主也比较建议这样做否则直接上手本节可能不好理解对 Page 的 Fetch 和 Unpin 操作。 由于代码量较多打算拆成上下两篇写完本篇介绍用到的数据结构和 B 树的查找和插入实现下一篇讲迭代器删除和并发控制。 关于 B 树的文字介绍就不赘述了查阅资料过程中发现维基百科的 B 树词条的算法描述不够具体推荐一个有比较具体的例子的博客 B树和B树的插入、删除图文详解 同时不建议参考那些插入和删除分 N 多种具体情况讨论的介绍 数据结构 B 树中有内部节点和叶节点两种结构它们存储的数据格式和内容不同。bustub 为我们设计好了下面这三个类 节点基类 BPlusTreePage 内部节点和叶节点的基类包含了节点类型、当前容量、最大/最小容量、ID、父节点 ID 信息从类结构上可以看做是两种节点的头信息。按照函数字面意思将其实现即可。可以规定 parent_page_id_ 为 INVALID_PAGE_ID 表示根节点。 内部节点 BPlusTreeInternalPageKeyType, ValueType, KeyComparator 内部节点首先看用到的三个泛型 KeyType, ValueType, KeyComparator。KeyType 不一定直接可用大于小于号比较所以引入了 KeyComparator从 cpp 文件中的实例化可以看出用的是 GenericKey 和 GenericComparator查看二者源码可以得到以下信息 GenericKey 可以调用 ToString() 函数得到其 int64 表示然后用 %ld 格式符打印。这对我们后面调试时非常重要。GenericComparator 的比较规则是左边小于右边时返回 -1左边大于右边时返回 1相等返回 0。 ValueType 代表的是指向子页面的指针从实例化可以看出实际只用了 page_id_t也就是 int。 数据存储上其理论结构应为 指针键指针键…键指针为方便存储实际上在头部多补了一个无效键从而可以用一个 pair 的数组存储 #define MappingType std::pairKeyType, ValueType ... class BPlusTreeInternalPage : public BPlusTreePage { ... private:// Flexible array member for page data.MappingType array_[1]; }array_[1] 等价于一个指针按照一般习惯应该在构造函数中为其 new 出一片大小为 max_size_ 的空间但实际上不需要这样做因为 Each BTree leaf/internal page corresponds to the content (i.e., the data_ part) of a memory page fetched by buffer pool. So every time you try to read or write a leaf/internal page, you need to first fetch the page from buffer pool using its unique page_id, then reinterpret cast to either a leaf or an internal page, and unpin the page after any writing or reading operations. 简单翻译一下就是 内部节点和叶节点对象都不是直接创建出来而是由一个 Buffer Pool 管理的 Page 的 data 部分类型转化而来所以要用到很少用很暴力的 reinterpret_cast。所以节点对象使用的是预先分配好的固定空间array_ 可以控制从该位置开始到 Page 的 data 结束为止的这一段空间。因此节点对象的生命周期也不是由 new 和 delete而是由我们上节实现的 BufferPoolManager 管理取一个页面用 FetchPage使用结束归还一个页面用 UnpinPage。同时也就能理解 BPlusTreePage 中 page_id_ 成员的另一个含义它不仅是 B 树中节点的编号同时也是这个节点使用的 Page 在 BufferPool 中的编号。 叶节点 BPlusTreeLeafPageKeyType, ValueType, KeyComparator 数据存储上叶节点也是一个 键值 的数组但不像内部节点那样第一个键无效。值的类型实际用的也只有一种RID。这个和我们本节的内容关系不大大致知道它是代表数据实际存放的位置即可。 BPlusTree 类代表整个 B 树 其主要成员有buffer_pool_manager_由外部传入root_page_id表示根节点 IDcomparator_KeyComparator 类型的对象用于键的大小比较leaf_max_size_ 和 internal_max_size_表示叶节点和内部节点的最大容量。我们需要实现 B 树的四个功能查找插入删除和迭代器。 Checkpoint 1查找插入和删除 实验非常贴心地将所有内容分为了两个 checkpoint其中 checkpoint 1 要实现查找插入和删除功能checkpoint 2 要实现迭代器和并发控制Autograder 上也对应有两个提交位置。下面放出的代码都只通过 checkpoint 1没有考虑加锁这样能更专注于讲解其本身的逻辑。本篇先讲查找和插入。 查找GetValue 给定一个键 xxx查找其是否在 B 树中存在。实现逻辑是先找到键可能在的叶节点然后扫描一遍叶节点的内容确定是否存在其中重点是前者。编写一个函数 GetLeafPage根据 B 树的规则应该从根节点开始每次在内部节点中找到 kixki1k_i x k_i1ki​xki​1 的位置然后沿着 viv_ivi​ 指针继续向下直到达到叶节点。函数实现如下 Tips循环时找内部节点中第一个比 xxx 大的键取其左侧的值即可k[0]k[0]k[0]无效而这样不能探测到 xxx 比所有 kkk 都大的情况所以要将 next_page_id 初始化为最右侧的键 在此基础上GetValue 的实现就很简单了 插入Insert 热身完毕下面进入本节第一个难点插入的实现。B 树的插入流程为 如果是空树创建一个叶节点作为根。注意涉及 root_page_id_ 更新时都要调用一次 UpdateRootPageId如果是第一次创建传 1 作为参数更新不用以下不再复述。从根节点向下查找到键值应该所在的叶节点。文档说明了不支持重复键所以先扫描一遍叶节点如果发现键存在则直接返回 false。如果叶节点 插入后 达到了 max_size则要进行分裂split创建一个新的叶节点将原节点的一半内容拷贝到新节点分裂点的键插入父节点该键对应的值指向新的叶节点。如果父节点不存在说明是第一个叶节点兼根节点需要创建一个新的根这种情况和 4 的建根可以合并处理如果父节点内部节点插入前 达到了 max_size也要递归进行分裂并向上插入此时还要调整原节点的一半子节点的 parent_id_ 指针指向新的内部节点。如果根节点满了则要创建一个新的根节点使得 B 树长高一层。 Tips特别注意这里叶节点和内部节点的判断条件是不同的摘一段文档原文 You should correctly perform splits if insertion triggers the splitting condition (number of key/value pairs AFTER insertion equals to max_size for leaf nodes, number of children BEFORE insertion equals to max_size for internal nodes). 第 1、2 步代码 第 3 步未溢出情况插入的具体逻辑可以放到 LeafPage 类中做所以添加一个 Insert 函数找到插入位置将所有后面的键值对后移一位再设置。由于 array_ 是有序的如果还想提高效率可以把找插入位置用二分搜索实现。 Tipscomparator_ 也要作为参数传入 Insert否则 LeafPage 中无法进行键的比较也就无法查找 叶节点溢出情况注意处理好 next_page_id_。移动一半数据的逻辑也可以放到 LeafPage 类中添加一个 MoveDataTo 函数 TipsMoveDataTo 不用真的对原叶节点后一半数据进行“抹除”修改 size 即可以后的新数据自然会覆盖掉这些数据。 真正的难点来了如何处理向父节点插入、同时处理父节点可能继续分裂的递归逻辑。需要想清楚的是在两次递归之间需要传递的数据是什么我的设计是传递两个子节点对象和分裂点的键。前者是为了获取到其父节点也可以对其本身的父节点指针进行更新后者是要插入父节点的键。进一步思考在第一轮传递的子节点对象是叶节点而后面每轮是内部节点看起来不统一但实际上我们需要这两个子节点只涉及到 page_id 的父子指针的更改所以传递的形式应设计为基类指针 BPlusTreePage *就可以兼顾这两种情况。 这里我用一个 while(true) 循环实现写成函数递归调用当然也可以。三个传递数据分别命名为 old_tree_pagenew_tree_page 和 split_key。 第一轮初始化和到达根节点的处理。正因为用的是 BPlusTreePage *所以可以兼顾 3 和 4即上一层是叶节点和内部节点两种情况的建根。 未到达根节点则在父节点进行插入。这里类似地我在 InternalPage 中也添加了一个 Insert 函数但要注意逻辑上有一丁点不同就是查找插入位置要从 1 开始。 如果父节点也溢出创建新的内部节点并移动一半数据。这里涉及到子节点的指针修改所以直接把逻辑写在这里了。最后将三个传递数据更新准备做下一轮处理。 细心的读者可能注意到上面达到跳出循环条件后没有 return true 而是写了 break这是因为在最后一轮循环结束后还要统一做一件事情释放最后两个页面。 如果你做完后本地测试和 AutoGrader 其它测试都能通过只有 ScaleTest 报错 SIGSEGVInternalPage 或 LeafPage 的函数比如 GetSize()访问了空地址则很可能是 Insert 函数中没有把所有 Fetch 的 Page 最后 Unpin 掉导致其一直占着 BufferPoolManager 的空间最终空间耗尽无法取到新页面FetchPage 返回 nullptr。检查也很简单改一下 BufferPoolManagerInstance 的代码例如每次 Fetch 和 Unpin 时打印一个信息看一下是不是所有的页面都被释放了0 号页面不被释放是正常的。 Debug 方法 这里我要吹爆 bustub 的开发组他们提供了一个非常好用的工具 b_plus_tree_printer可视化展现树的结构帮助检查你的实现效果是否正确。 更感人的是他们还提供了一个打印正确实现的 B 树的在线版本可以与自己本地的效果对比泪目 本篇内容到此结束下一篇继续讲迭代器删除和并发控制的实现
http://www.hkea.cn/news/14438711/

相关文章:

  • 基于MVC网站建设课程设计报告石景山青岛网站建设
  • 交易类网站建设功能表西部数码个人网站
  • 申请免费网站做网站的语言叫什么
  • wordpress网站页面打开很慢上海装修公司前十强排名榜
  • 郑州市哪里有网站建设起飞页自助建站平台的特点
  • 濮阳专业做网站公司crm客户关系系统
  • 潍坊做网站的深圳专业网站建设
  • 泰安集团网站建设地点专门做机器人的网站
  • 描述网站开发的过程临沂建设企业网站
  • 网站开发的晋升晋升空间路径网易企业邮箱怎么设置
  • 网站搭建要多少钱大朗镇网站建设
  • 电子商务网站建设实验心得淄博建设企业网站
  • 朋友用我的vps做网站中国制造网官方网站首页
  • 郑州建站网网络营销的主要特点
  • 园区网站建设服务公司寿光哪里做网站
  • 基于淘宝的网站开发分析南京建设监理协会网站
  • 做网站的公司如何运营360网站免费推广怎么做
  • 用php做网站用到的工具优秀网络小说推荐
  • 徐州seo网站推广工作室官网源码
  • 浮山网站建设wordpress+搭建知识库
  • 太原网站建设公司排名知名商城网站建设报价
  • 鸿顺里网站建设广西网站建设价钱
  • 网站目录wordpress手机网站模版
  • 免费行情软件网站下载大全爱类似12306网站开发
  • 简约网站版式网站首页模板免费下载
  • 网站开发实例及研究做网站怎么把导航每个页面都有
  • 建筑培训网站有哪些wordpress无法发表文章
  • 响应式网站如何实现徐州网络推广
  • 淮南市建设工程质量监督中心网站手机在线做ppt的网站有哪些
  • 网站文字大小品质好的英文