缓存遗忘堆栈和队列的复杂性

时间:2012-08-27 02:34:20

标签: algorithm cache-oblivious

我已经读过可以使用双倍数组实现缓存不经意的堆栈。

有人可以解释一下分析如何使每个推送和弹出具有1/B摊销的I / O复杂性吗?

2 个答案:

答案 0 :(得分:3)

堆栈支持以下操作:

  • 流行音乐

虽然这两个操作可以使用带有O(1)push和O(1)pop的单链表执行,但它会遇到缓存问题,因为存储的元素通过内存分散。对于这种方法,我们将推到列表的前面,然后从列表的前面弹出。

我们可以使用dynamic array作为我们的数据结构,然后按下并弹出到数组的末尾。 (我们将跟踪数组中最后填充的位置作为索引,并在推送和弹出元素时对其进行修改)。

弹出将是O(1),因为我们不需要调整数组的大小。

如果阵列末尾有一个额外的空格,推送将为O(1)。

问题是当我们尝试推送元素但没有空间时。在这种情况下,我们创建一个两倍大(2n)的新数组,然后复制n个元素中的每一个,然后推送元素。

假设我们有一个已经大小为n的数组,但是从空开始。

如果我将n + 1个元素推到数组上,那么前n个元素需要O(1)* n = O(n)时间。

+1元素花费O(n)时间,因为它必须构建数组的新副本。

因此将n + 1个元素推入数组是O(2n),但是我们可以去除常量,只是说它是元素数的O(n)或线性。

因此,推动单个元素可能需要比常量操作更长的时间,推动大量元素需要花费大量工作。

动态数组是缓存友好的,因为所有元素尽可能彼此接近,因此多个元素应位于相同的缓存行中。

答案 1 :(得分:1)

我认为标准堆栈是缓存无关紧要的。您只有1 / B的访问故障,因为任何推/弹序列必须是相邻的地址,因此每B操作只能命中一个新的缓存行。 (注意:参数需要至少2个缓存行以防止颠簸。)