C++ 我需要一个容器,支持有效的随机访问和O(k)插入和删除
我又试着问同样的问题,但最后我问了一个不同的问题,没有提供关于我的问题的基本信息 我实现了一个数据结构,它是一个树。该树的每个节点都有一个数组/向量/(随机访问结构),其所有子节点可以是任意多个。元素的插入/移除很容易,因为我们总是将该数组中的元素数加倍/除以2 这就是C++ 我需要一个容器,支持有效的随机访问和O(k)插入和删除,c++,algorithm,pointers,data-structures,C++,Algorithm,Pointers,Data Structures,我又试着问同样的问题,但最后我问了一个不同的问题,没有提供关于我的问题的基本信息 我实现了一个数据结构,它是一个树。该树的每个节点都有一个数组/向量/(随机访问结构),其所有子节点可以是任意多个。元素的插入/移除很容易,因为我们总是将该数组中的元素数加倍/除以2 这就是O(k)插入/删除在本文中的含义。我们有k元素,我们追加k更多或删除k/2。到目前为止,重建整个数据结构还不错。动态数组(或向量)可以工作 提出问题的操作如下。有时,我们必须将具有子节点的节点“拆分”,这意味着我们将子节点“拆分”
O(k)
插入/删除在本文中的含义。我们有k
元素,我们追加k
更多或删除k/2
。到目前为止,重建整个数据结构还不错。动态数组
(或向量
)可以工作
提出问题的操作如下。有时,我们必须将具有子节点的节点“拆分”,这意味着我们将子节点“拆分”到不同的节点中。我们潜水的方式是连续分组。我想,这种拆分最有效的方法是,在每个新节点的子节点所在的位置和子节点的数量(假设每个节点取k
子节点)为每个节点设置一个指针。但是,这些子级的数量可能会发生变化,并且不会影响其同级(甚至更糟的是,整个树),即插入的执行时间应该是O(k)
,而不是O(n)
。我们怎么做
一个简单但低效的解决方法是,每次分割一个节点时,我们都会将子节点的“大”数组替换为多个(与分割的部分一样多)“小”动态数组
以下每个“框”都是随机访问结构
来一杯怎么样
它得到了摊销的
O(1)
access、insert和remove平均情况O(n)
最坏情况。根据您对正在实现的树结构的描述,最好创建一个新的数据结构来模拟您的树。特别是当您已经在跟踪节点之间的指针时
如果我理解您的语句,那么树中的每个节点都将包含子节点指针的向量。当需要拆分节点时,可以创建新节点,每个节点接收子指针向量的一段,新创建的节点将插入父节点的节点向量中
例如:
N1->N2->(n3,n4,n5,n6,n7,n8)
将N2拆分为两个节点:N1->(N2\u 1,N2\u 2)
withN2\u 1->(n3,n4,n5)
和N2\u 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)
节点的结构可能如下所示(非常简化):
类节点{
媒介儿童;
节点*父节点;
};
更大的树结构将是许多这些节点连接在一起,就像二叉树一样。将节点添加到树上的任何一个节点只会将项目添加到该节点的
子节点
成员。其他一切都没有受到影响。在我看来,你似乎在试图重新创造
B+树的一种变体是存储子元素的数量而不是适当的键,这允许有效的随机访问(log n
),而您实际上可以控制这些因素
例如,数据库的一个公共因子约为1000,这意味着树的第一级是根,第二级最多可包含1000个子级,第三级最多可包含1000000子级等等
如果对象少于100000000,则意味着最多3次解引用,这是非常有效的
已经有一个Python模块,用这种技术编写,目的是用B+树替换传统的<代码>列表>代码>类(实现为C++ <代码>向量>代码>,以获得更大的效率。可以找到性能测量值。
预计序列会有多大?平均而言,在预测的最坏情况下,您预计一个序列中会有多少个元素?平均而言,在最坏的情况下,您希望每个元素有多大(以字节为单位)?结构中所有节点的子节点的总数可能与此结构存储的元素数相同,该元素数任意大,并表示为n
(大数组)。另一方面,2是正确的,但在实际应用中,n很少是任意大的;小n的理想数据结构可能与大n的理想数据结构大不相同。优化似乎为时过早。你说std::vector/dynamicarray resize很好,尽管它可能需要执行新的分配并复制每个元素,但是拆分是一个大问题?它执行更多的分配,但复制的级别相同。。。。你有一个你描述过的工作系统吗?我要求的不仅仅是辩论——如果你量化你的问题,你会得到更多、更有用/更相关的帮助。@James我实际上对大量的投入感兴趣@Tony整个项目都是关于这个数据结构的。split
操作是整个性能的关键。只要复杂性是O(k)
,那么向量的大小调整就可以了,也就是说,我们讨论的向量包含k
元素,并插入/删除O(k)
元素。另一方面,如果向量的大小为n>>k
(由于处理拆分的方式),则成本会爆炸到O(k)
。请注意摊销O(1
class Node {
vector<Node *> children;
Node * parent;
};