C++ 基于数组的Deques:为什么AddFront/RemoveFront为O(1)?
对于基于阵列的deque,为什么从前面添加和删除弹药是O(1)?对我来说,它始终是O(n)是有意义的,因为任何一种操作都意味着数组的当前值需要“移动”到0索引的右侧进行添加,然后移动到左侧进行删除 我的教授说你不需要改变,只需要更新hi和lo。我不完全清楚他是什么意思 <>这不是一个C++问题本身,但我试图用这种语言理解它。 < p>你有2个指针(HI和LO),指向Deq的每个末端。 :C++ 基于数组的Deques:为什么AddFront/RemoveFront为O(1)?,c++,queue,dynamic-arrays,deque,C++,Queue,Dynamic Arrays,Deque,对于基于阵列的deque,为什么从前面添加和删除弹药是O(1)?对我来说,它始终是O(n)是有意义的,因为任何一种操作都意味着数组的当前值需要“移动”到0索引的右侧进行添加,然后移动到左侧进行删除 我的教授说你不需要改变,只需要更新hi和lo。我不完全清楚他是什么意思 这不是一个C++问题本身,但我试图用这种语言理解它。 < p>你有2个指针(HI和LO),指向Deq的每个末端。 : 我不理解DEC++的精确C++实现,但这是我对你教授关于时间复杂度的合理化的最好尝试: 从和中,似乎数据是非连续
我不理解DEC++的精确C++实现,但这是我对你教授关于时间复杂度的合理化的最好尝试: 从和中,似乎数据是非连续存储的 是另一个StackOverflow问题,它提供了有用的图像和一些丰富的信息 注意
start
是如何简单地指向前面的,但是也可以有未使用的部分。因此,如果我们可以简单地将旧的正面标记为“未使用”,或者在背面标记为“未使用”,那么在弹出正面时可能不需要移动所有内容
编辑:我的猜测是,因为开头和结尾都有未使用的部分,所以添加到前面或后面相对比较容易,直到正如John在自己的回答中所说的,您的空间用完了/“命中边界”。我假设它只是将指针移动到数组中的“前面”和“后面”不同位置。这会改变队列的逻辑结构,而不必在队列中的所有内容上来回移动。该死,我应该意识到它使用指针。好的,现在有道理了。但是,如果您添加到前端,您是否仍然需要移动/移动项目?是的,在添加时会发生移动,但仅当两端的空间用完时才会发生。假设您创建了此数据:{3,5,10,12},然后执行了五个addfronts。(不要担心尺寸/空间)。每个addfront是否意味着您必须进行转换,并且在每个addfront之后,lo将引用新值?这取决于具体情况。例如:您的数组足够大,可以容纳100个数字,示例中的3个位于数组[50]
,12个位于数组[53]
。那么你的5个addfronts就不需要任何移位了。@ohbrobig当你分配一个新的内存块时,你把旧的元素复制到块的中间而不是开始。然后,您可以在不移动的情况下添加到前面或后面,直到再次撞到边界。std::deque
必须是非连续的,因为它对迭代器无效等有限制。在任意一端插入摊销O(1)并不是绝对必要的。我试图研究你所说的“迭代器失效”是什么意思,因为我不熟悉这个术语。根据我试图研究的内容,我假设这些“约束”是因为一个deque的特性(只能弹出/推前/推后)。这是真的吗?除此之外,我不明白为什么“迭代器失效约束”需要“非连续”存储。你能解释一下这个要求吗?我错了,迭代器可以在插入时失效,但引用不能。这意味着每个元素都需要保留在其原始内存位置,不能随着deque
大小的增加而移动-这就是为什么它必须是非连续的。与vector
相比,每当容器改变大小时,引用就会失效。有关规则,请参阅。感谢您提供的额外链接。我将继续研究您提供的要点[:
"aaaaa" <- hi
"bbbbb"
"ccccc"
"ddddd"<- lo
//"aaaa" is still in the array but not considered part of the deque
"bbbbb" <- hi
"ccccc"
"ddddd" <- lo
class Deque {
int deque[10];
int hi, lo; // Initialize in constructor to -1 to flag deque is empty
public:
void push_front(int x) {
// First time, add to middle of array
if (-1 == lo) {
hi = lo = 5; // Since array size is 10;
deque[5] = x;
}
// Shift required?
else if (lo == 0) {
// Check if deque is full
if (9 == hi) {
// return error or get more space
}
else {
// Shift by one
// More optimally you would shift enough to move data to center of array
for (int i = hi; i >= lo; --i) {
deque[i + 1] = deque[i];
}
// Update hi
hi += 1;
// Store in lo - lo remains at 0
deque[0] = x;
}
}
// No shift required
else {
deque[--lo] = x;
}
}
// TODO: push_back, pop_front, pop_back