Java 如何在恒定时间O(1)中清除循环数组队列
我试图找到一种方法来实现高效的Java 如何在恒定时间O(1)中清除循环数组队列,java,queue,Java,Queue,我试图找到一种方法来实现高效的clear,以在固定时间内清除循环数组队列 我尝试了Array.fill()并用null值填充数组,但它仍然必须通过数组,这意味着O(n)。我想说,这个问题的答案有点取决于您的要求以及什么是常量操作 一种方法是创建一个具有固定大小的新数组(即O(1))并放弃对旧数组的引用,然后将指针重置为其初始值。使用这种方法,后续的插入操作将需要增加数组的大小 另一种方法可能是初始化一个与当前存储元素的数组大小相同的新数组,并放弃对旧数组的引用。这可能是一个错误 第三种方法是用户
clear
,以在固定时间内清除循环数组队列
我尝试了
Array.fill()
并用null
值填充数组,但它仍然必须通过数组,这意味着O(n)。我想说,这个问题的答案有点取决于您的要求以及什么是常量操作
头部
和尾部
指针即可。但是,请注意,这不会清除对数组中(可能是重量级)对象的引用,这可能会导致应用程序内存泄漏,因为仍然存储在其中的对象无法进行垃圾收集clear
操作(基本上只是一个循环数组队列)的实现,您可以看到它通过以下两个操作使用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;
}
}
/**
*从该数据集中删除所有元素。
*此调用返回后,deque将为空。
*/
公共空间清除(){
圆形耳(元素、头部、尾部);
头=尾=0;
}
/**
*将从数组索引i开始直至索引结束的插槽置零。
*条件i==结束意味着“空”-无事可做。
*/
私有静态void circular(对象[]es,int i,int end){
//断言0我想说,这个问题的答案有点取决于您的需求以及什么是常量操作
一种方法是创建一个固定大小的新数组(即O(1))并放弃对旧数组的引用,然后将指针重置为其初始值。使用这种方法,后续的插入操作需要增加数组的大小
另一种方法可能是初始化一个与当前存储元素的数组大小相同的新数组,并放弃对旧数组的引用
第三种方法是用户在问题的评论部分建议的方法。只需移动头
和尾
指针即可。但是,请注意,这不会清除对(可能是重量级)的引用数组中的对象,这可能会导致应用程序内存泄漏,因为仍然存储在其中的对象无法进行垃圾收集
查看的clear
操作(基本上只是一个循环数组队列)的实现,您可以看到它通过以下两个操作使用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;
}
}
/**
*从该数据集中删除所有元素。
*此调用返回后,deque将为空。
*/
公共空间清除(){
圆形耳(元素、头部、尾部);
头=尾=0;
}
/**
*将从数组索引i开始直至索引结束的插槽置零。
*条件i==结束意味着“空”-无事可做。
*/
私有静态void circular(对象[]es,int i,int end){
//断言0考虑这样一个事实,即如果您不在您的“代码”>“头部< /COD>”和“代码>尾部< /代码>指针的界限之外,您不需要关心您队列中的任何给定位置中的内容。因此,如果您只将这两个指针移回数组的第一个元素,并将该元素清空,那么就无法区分该值。就实际功能而言,@Jordan我不会这么说。如果你真的想清除数组,那么(可能是重量级的)对象可以是垃圾收集的,那么你所描述的行为不是你想要的。@约旦,事实上,如果你在数组中没有空引用,这可能是内存泄漏。想象一个对象保持对大对象的引用,它将保留在数组中,防止引用的对象被GC收集。如果队列中的任何给定位置超出了head
和tail
指针的边界,则不需要真正关心该位置中的内容。因此,如果将两个指针移回数组的第一个元素并将该元素置空,那么就实际函数而言,这与清除队列中的值是无法区分的“我不会这么说的。如果你真的想清理你的阵型,那么(可能是重量级的)对象可以被垃圾收集,那么您描述的行为就不是您想要的。@Jordan事实上,如果您不清空数组中的引用,这可能是内存泄漏。假设一个对象保留对大型对象的引用,它将保留在数组中,并阻止被引用的对象被GC收集。