我需要一个支持高效随机访问和O(k)插入和删除的容器

时间:2010-09-28 01:39:41

标签: c++ algorithm pointers data-structures

我再次尝试同样问question,但我最后提出了一个不同的问题,因为我没有提供有关我问题的重要信息。

我实现了一个树的数据结构。该树的每个节点都有一个数组/向量/(随机访问结构),其所有子节点可以是任意多个。插入/删除元素很容易,因为我们总是将这个数组中元素的数量加倍/除以2。

这就是O(k)插入/删除在此上下文中的含义。我们有k个元素,我们会追加k个或删除k/2。到目前为止,重建整个数据结构很好。 dynamic array(或vector)有效。

提出问题的操作如下。有时我们必须"split"一个节点有n个孩子,这意味着我们在不同的节点之间“划分”子节点。我们潜水的方式是连续的。对于这种拆分,最有效的方法是,我想,每个新节点都有一个指针,指向其子节点的位置和有多少节点(假设每个节点需要k个子节点)。但是,这些孩子的数量可能会改变,这不应该影响其兄弟姐妹(甚至更糟糕的是整个树),即插入的执行时间应该是O(k)而不是O(n)。我们怎么做?

一个简单但低效的解决方法是,每次我们拆分节点时,我们将children的“大”数组替换为许多(与拆分部分一样多)“小”动态数组。 / p>

以下每个“框”都是随机访问结构。

alt text

3 个答案:

答案 0 :(得分:3)

hashmap怎么样?

已经摊销O(1)访问,插入和删除平均情况; O(n)最糟糕的情况。

答案 1 :(得分:1)

根据您所实现的树结构的描述,最好创建一个新的数据结构来模仿您的树。特别是如果你已经在跟踪节点之间的指针。

如果我理解你的陈述,你树中的每个节点都会包含一个子节点指针向量。当您需要拆分节点时,您可以创建新节点,每个节点都接收子节点向量的一段,并且新创建的节点将插入父节点的节点向量中。

例如:

N1->N2->(n3,n4,n5,n6,n7,n8)将N2拆分为两个节点:N1->(N2_1, N2_2) N2_1->(n3,n4,n5)N2_2->(n6,n7,n8)

(对不起,我不知道如何轻松画树......)

这样,您只是重新链接内存而不是复制,访问通常是log n。此外,这在代码中给出了树结构的正确表示。

编辑添加示例:

再次假设我们有N1->N2->(n3,n4,n5,n6,n7,n8)。如果N1需要添加新节点,则唯一的影响是在N1节点上:N1->(N2,N9)->(n3,n4,n5,n6,n7,n8)

节点的结构可能是这样的(非常简化):

class Node {
  vector<Node *> children;
  Node * parent;
};

较大的树结构将是许多这些节点都链接在一起,就像二叉树一样。要将节点添加到树上的任何一个节点,只会将项添加到该节点的children成员。没有其他因素受到影响。

答案 2 :(得分:1)

在我看来,你正试图重新发明B+ Tree ......

B + Tree有一个变体,它包含存储子元素的数量而不是正确的密钥,这允许有效的随机访问(log n),这是您实际控制的因素。

例如,数据库的公共因子大约为1,000,这意味着树的第一级是根,第二级最多可包含1,000个子项,第三级最多可包含1,000,000个等等...

如果您的对象少于1,000,000,000个,则表示最多3个解除引用,这非常有效。

有一个使用这种技术编写的python模块,名为blist,旨在用B + Tree替换传统的list类(实现为C ++ vector)大件物品的效率更高。可以找到性能测量here