std :: deque实际上在开始时是否插入了固定时间?

问题描述 投票:6回答:1

我知道以前曾问过类似的问题。但请完整阅读,然后作为副本关闭。

标准说:

双端队列是支持随机访问迭代器(27.2.7)的序列容器。另外,它支持在开始或结束时进行恒定时间的插入和擦除操作;在中间插入并删除线性时间。

但是,它也在同一条款中说:

本条中的所有复杂性要求仅根据对所包含对象的操作次数来说明。 [示例:vector<vector<int>>类型的复制构造函数具有线性复杂度,即使复制每个包含的vector<int>本身的复杂度也是线性的。 —结束示例]

这不是说,在deque<int>开头的插入允许采用线性time,只要它在执行时不超过恒定数量的operations已经在双端队列中的int个对象和要插入的新int对象?

例如,假设我们使用“大小为K的向量的向量”来实现双端队列。似乎我们在开始处每插入K次后,必须在开始处添加一个新的size-K向量,因此必须移动所有其他size-K向量。这将意味着开始时插入的时间复杂度为O(N / K),其中N是元素总数,但是K是常数,所以这只是O(N)。但这似乎是标准所允许的,因为移动大小为K的向量不会移动其任何元素,并且“复杂度要求”仅在所包含的[C0 ]对象。

标准真的允许这样做吗?还是应该将其解释为具有更严格的要求,对包含的对象进行恒定的操作数plus恒定的附加时间?

c++ time-complexity language-lawyer complexity-theory deque
1个回答
0
投票

例如,假设我们使用“大小为K的向量”来实现双端队列。

那不是有效的实现。插入int的前面会使容器中的所有指针/引用/迭代器无效。需要vector才能使前面插入的any指针/引用/迭代器(在开始迭代器之外)无效。

但是让我们暂时忽略它。

但是似乎这是标准所允许的,因为移动大小为K的向量不会移动其任何元素,并且所包含的“复杂性要求”“仅根据操作次数来说明” int对象。

是的,那是允许的。确实,deque的实际实现与其并没有什么不同(尽管出于明显的原因,它们并未使用deque本身)。 std::vector实现的大致轮廓是一个指向块的指针数组(在前面和后面都有增长空间),每个块最多包含X个项目以及指向下一个/上一个块的指针(指向快速进行单元素迭代)。

如果在前面或后面插入足够的元素,则必须增加块指针数组。这将需要一个相对于deque中的项目数量为线性时间的运算,但是实际上并不对这些项目本身进行运算,因此不算在内。

如果没有此规定,我不确定deque的唯一功能集(快速插入/插入随机访问)是否可以实现。

© www.soinside.com 2019 - 2024. All rights reserved.