【问题标题】:How to clear a circular array queue in constant time O(1)如何在恒定时间内清除循环数组队列 O(1)
【发布时间】:2019-10-28 20:48:37
【问题描述】:

我正在尝试找到一种方法来实现高效的clear 以在恒定时间内清除循环数组队列。

我试过Array.fill() 并用null 值填充数组,但它仍然必须通过数组,这意味着 O(n)。

【问题讨论】:

  • 请考虑这样一个事实,即如果队列中的任何给定位置超出 headtail 指针的范围,您实际上并不需要关心它。因此,如果您只是将两个指针移回数组的第一个元素并将该元素清空,就实际功能而言,这与清除队列中的值没有区别。
  • @Jordan 我不会这么说的。如果您真的想清除数组以便(可能是重量级)对象可以被垃圾收集,那么您描述的行为不是您想要的。
  • @Jordan 事实上,如果你不清空数组中的引用,这可能是内存泄漏。想象一个对象保留对大对象的引用,它将保留在数组中并防止被引用的对象被 GC 收集。

标签: java queue


【解决方案1】:

我会说这个问题的答案在某种程度上取决于您的要求以及什么是持续操作。

  1. 一种方法是创建一个具有固定大小(O(1))的新数组并丢弃对旧数组的引用,然后将指针重置为其初始值。使用这种方法,后续的插入操作将需要增加数组的大小。
  2. 另一种方法可能是初始化一个与当前存储元素的数组大小相同的新数组,并丢弃对旧数组的引用。这可能constant time operation
  3. 第三种方法是用户Jordan 在您问题的评论部分建议的方法。只需移动headtail 指针。但是,请注意,这不会清除对数组中(可能是重量级)对象的引用,这可能会导致应用程序中的内存泄漏,因为仍然存储在其中的对象无法被垃圾回收。

ArrayDequeclear操作的实现(基本上就是一个循环数组队列),通过以下两个操作可以看出它采用了O(n)的方式:(1)清零元素,(2) 重置指针。

/**
 * Removes all of the elements from this deque.
 * The deque will be empty after this call returns.
 */
public void clear() {
    circularClear(elements, head, tail);
    head = tail = 0;
}

/**
 * Nulls out slots starting at array index i, upto index end.
 * Condition i == end means "empty" - nothing to do.
 */
private static void circularClear(Object[] es, int i, int end) {
    // assert 0 <= i && i < es.length;
    // assert 0 <= end && end < es.length;
    for (int to = (i <= end) ? end : es.length;
         ; i = 0, to = end) {
        for (; i < to; i++) es[i] = null;
        if (to == end) break;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-30
    • 2018-11-13
    • 2013-11-04
    • 1970-01-01
    • 2011-05-03
    • 2015-05-08
    相关资源
    最近更新 更多