我再次尝试同样问question,但我最后提出了一个不同的问题,因为我没有提供有关我问题的重要信息。
我实现了一个树的数据结构。该树的每个节点都有一个数组/向量/(随机访问结构),其所有子节点可以是任意多个。插入/删除元素很容易,因为我们总是将这个数组中元素的数量加倍/除以2。
这就是O(k)
插入/删除在此上下文中的含义。我们有k
个元素,我们会追加k
个或删除k/2
。到目前为止,重建整个数据结构很好。 dynamic array
(或vector
)有效。
提出问题的操作如下。有时我们必须"split"
一个节点有n
个孩子,这意味着我们在不同的节点之间“划分”子节点。我们潜水的方式是连续的。对于这种拆分,最有效的方法是,我想,每个新节点都有一个指针,指向其子节点的位置和有多少节点(假设每个节点需要k
个子节点)。但是,这些孩子的数量可能会改变,这不应该影响其兄弟姐妹(甚至更糟糕的是整个树),即插入的执行时间应该是O(k)
而不是O(n)
。我们怎么做?
一个简单但低效的解决方法是,每次我们拆分节点时,我们将children
的“大”数组替换为许多(与拆分部分一样多)“小”动态数组。 / p>
以下每个“框”都是随机访问结构。
答案 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)