【发布时间】:2009-09-11 02:22:32
【问题描述】:
出于各种原因,我正在编写 B+ 树,我来这里是为了询问有关其节点实现的问题。我的节点目前看起来像:
struct BPlusNode
{
public:
//holds the list of keys
keyType **keys;
//stores the number of slots used
size_t size;
//holds the array of pointers to lower nodes NULL if this is a leaf node
BPlusNode **children;
//holds the pointer to the next load to the 'left'
BPlusNode *next;
//Data page pointers NULL if this is a branch node
Bucket **pages;
};
如您所见,我当前的实现是在我想知道是否应该使用 * * 或 * 的地方使用 *。
我很清楚 * * 需要两个取消引用操作,因此比简单地使用 * 慢,但是这个类使用了大量的递归,并且将指针传递给递归的子调用要方便得多职能。要使用 * 执行此操作,我需要进行指针运算并传递结果指针。
带**
someFunction(BPlusNode* currNode)
{
......
someFunction(currNode->children[ChildIndex]);
}
带 *
someFunction(BPlusNode* currNode)
{
......
someFunction((currNode->children) + ChildIndex);
}
我可以看到在 * * 版本中需要额外读取内存以生成所需的指针,但 * * 版本对我来说也更容易考虑(它更符合我对绘制图表的看法在“计算机编程艺术”和维基百科中)。
有没有人有任何想法?对第三种选择的建议?证明为什么一个优于另一个?等等?
编辑:
我可能会将其发布为下面的答案,但我刚刚意识到使用 * * 方案我不需要复制每个子节点或存储桶的全部内容,如果我想将一个插入到数组的中间(即调整数组的大小) .如果在我重新分配数组时 * 方案有 20 个子节点,我需要复制 20*sizeof(BPlusNode) 字节,而不是 * * 方案的 20*sizeof(BPlusNode*) 字节。
另一方面,我想到,由于我执行所有插入和页面拆分都是预先完成的,因此执行它们的效率提高可能是不必要的,并且在搜索中 * over * * 的好处超过了它。
【问题讨论】:
-
由于这是标记为 C++,是否有某些原因您不能通过引用传递指针而不是进行指针运算?
-
据我了解,它做一些类似 someFunction(BPlusNode*& currNode).... 然后通过 someFunction(currNode->children[ChildIndex]) 调用它,会比 * * 更糟糕。 [] 与 *(currNode->children + ChildIndex) 基本相同,因此,与 * * 方案相同的是指针运算,然后是取消引用。与 * * 方案不同,对象的 this 指针必须被检索并传递。所以在我看来,在效率上,它至少相当于**方案。也许更糟。
-
@James:我确定 grayfade 建议使用
someFunction(BPlusNode& currNode)的签名。这在功能上(在性能方面)与someFunction(BPlusNode* currNode)相同,但看起来更简洁,并且避免了意外更改指针(而不是指针对象)可能导致的错误。
标签: c++ data-structures pointers