高级搜索树(伸展树 逐层伸展)
高级搜索树(伸展树 逐层伸展)
高级搜索树(伸展树 算法实现)
问题:关于伸展树删除算法的疑问
在教材中,伸展树的删除算法为先将被删除节点v伸展至树根,删除树根,再将v的后继m伸展至树根,最后将其与原树的左子树连接起来。
再此过程中,大部分的情况下要进行2次伸展操作,我的疑问是:是否可以直接调用BST::remove()将节点v删除,并将v的接替者m伸展至树根(而不是非教材中写的_hot),也能保证数据局部性,从而省去一次伸展操作呢?(by 土地使用权证 )
答:好问题!不过你的方法固然可行,但我以为课上介绍的方法更好:
你的方法也要做两次查找(v->BST::search(x)和BST::succ(v)),总体时间成本相同,但需要调用父类的两种不同接口
按照课上介绍的方法,只需调用本身的查找接口两次,而且参数一样(Splay::search(x)),与父类的实现无关(by Junhui 老师)
高级搜索树(B树 大数据)
高级搜索树(B树 结构)
题目:
为什么AVL树每次IO只能取一个节点?
之所以引入B-树,是为了更好地配合外存IO,所以把一个节点做得大一点,一次IO就能读取更多节点了,是这样理解对吧?
那么我想问,为什么在外存中组织AVL树,每次IO就只能读入一个节点呢?树的数据结构在磁盘上存储形式是怎么样的呢?
(by 莎莫 )
答:首先,你组织的AVL树是在内存里,不是在磁盘上。这也会涉及IO问题,即从内存到CPU的cache的IO问题。
假设cache每64 bytes是一个block(cache的block比较小,一般只有64 bytes量级;而外存到内存一个block比较大,典型的一个页是 4KB),那么读取任何数据,就会把它所在的block全读进来。比如一个数组int a[1000];,你访问a[101],那么它所在的block(比如说a[96]~a[111])都读进来了。
节点是new出来的,new不保证连续。即使new连续(或者你自己先申请了一个buffer,然后每次手动分配),建树的顺序你是知道的吧,这就是它在内存上的存储形式。一般你也不会去特意保证同层节点(或很可能连续访问的节点)在内存空间上连续。(yuantailing 老师)
答:
哦哦哦,似乎明白了,所以组织成“大节点”是为了保证连续性,一次读入就能够得到可连续操作的多个节点,而AVL树由于本层和下层节点一般不是连续存储,所以一次读入(即使读入的不止一个节点)很可能只能处理一个节点,处理下一个节点又要花费一次IO。
谢谢老师的解答!( by 莎莫 )
答:所以B树的node结构必须是vector实现才能保证其在磁盘上物理连续,而不能是列表结构。相当于这种数据结构既用到了列表结构(每个节点,物理不连续),又用到了向量(每个节点内部的多个值,物理连续)。(by 张博通)
高级搜索树(B树 查找)
问题:节点内向量查找时间复杂度
请问关于b树单个节点的查找,如果是仅考虑向量内查找而不是考虑整个树中的查找,那么单独考虑节点而不考虑内外存访问时间差异的话,节点内时间复杂度不应该按照向量时间复杂度来算吗,具体时间由向量长度决定,那这样还可以视为常数级别o(1)吗(by 王者强 )
答:如果所谓的节点内时间复杂度指的是顺序查找m个关键码的话,由于m是一个常数,因此也是O(1)的。另外B树本身就是基于内外访存时间差异所设计的。(by ydc123 老师)
问:B树查找
最后的视频演示的B树查找说明节点间是存在顺序性的,那么节点内的各个关键码是否也存在顺序性呢?如果存在顺序性应该使用2分查找效率更高吧。(by zhong12a )
答:B树节点的规模(其中所含整数关键码的数量)通常在200~300之间,此时用顺序查找反而比二分查找更快。(by Junhui 老师)