我知道以前曾问过类似的问题。但请完整阅读,然后作为副本关闭。
标准说:
双端队列是支持随机访问迭代器(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恒定的附加时间?
例如,假设我们使用“大小为K的向量”来实现双端队列。
那不是有效的实现。插入int
的前面会使容器中的所有指针/引用/迭代器无效。需要vector
才能使前面插入的any指针/引用/迭代器(在开始迭代器之外)无效。
但是让我们暂时忽略它。
但是似乎这是标准所允许的,因为移动大小为K的向量不会移动其任何元素,并且所包含的“复杂性要求”“仅根据操作次数来说明” int对象。
是的,那是允许的。确实,deque
的实际实现与其并没有什么不同(尽管出于明显的原因,它们并未使用deque
本身)。 std::vector
实现的大致轮廓是一个指向块的指针数组(在前面和后面都有增长空间),每个块最多包含X个项目以及指向下一个/上一个块的指针(指向快速进行单元素迭代)。
如果在前面或后面插入足够的元素,则必须增加块指针数组。这将需要一个相对于deque
中的项目数量为线性时间的运算,但是实际上并不对这些项目本身进行运算,因此不算在内。
如果没有此规定,我不确定deque
的唯一功能集(快速插入/插入和随机访问)是否可以实现。