Java 对于ArrayQue,有没有一种方法可以实现时间复杂度为O(1)的检索(get())?

Java 对于ArrayQue,有没有一种方法可以实现时间复杂度为O(1)的检索(get())?,java,time,deque,arraydeque,Java,Time,Deque,Arraydeque,我尝试将ArrayQue用于一个类,该类的addfront、addback和retrieval的时间复杂度应该是O(1)。我只能想到使用toArray()进行检索,不幸的是它是O(n)。有没有一种方法可以实现一个O(1)的ArrayQueue检索方法 我浏览了ArrayDeque的源代码,没有一个方法可以通过索引访问任意数组元素。这是在O(1)中执行操作所必需的 不过,实现满足您需求的自己的类应该不会太难。搜索“循环缓冲区”。如果数组溢出,请将整个内容复制到一个新的双倍大小的数组中。当然,这不能

我尝试将ArrayQue用于一个类,该类的addfront、addback和retrieval的时间复杂度应该是O(1)。我只能想到使用toArray()进行检索,不幸的是它是O(n)。有没有一种方法可以实现一个O(1)的ArrayQueue检索方法

我浏览了
ArrayDeque
的源代码,没有一个方法可以通过索引访问任意数组元素。这是在O(1)中执行操作所必需的

不过,实现满足您需求的自己的类应该不会太难。搜索“循环缓冲区”。如果数组溢出,请将整个内容复制到一个新的双倍大小的数组中。当然,这不能在固定时间内完成,但添加仍将在摊销固定时间内完成,这与
ArrayDeque
相同

我假设
get()
的意思是通过从前面或后面计数的队列中元素的位置/索引来检查(不删除)元素

编辑

我想另一种方法是使用数组并找到一种方法 时间是恒定的,但我不知道怎么做

下面是一个简单的实现。请根据您的需要进一步发展。其想法是使用循环缓冲区,如果旧的数组太小,则复制到新数组。我相信,
ArrayDeque
使用了相同的想法

public class MyArrayDeque<E> {

    private Object[] elements;
    
    // Index to first element.
    private int front = 0;
    // Index to first free space after last element.
    // back == front means queue is empty (not full).
    private int back = 0;
    
    public MyArrayDeque(int initialCapacity) {
        if (initialCapacity < 0) {
            throw new IllegalArgumentException("Initial capacity must not be negative");
        }
        // There’s always at least 1 free space, so add 1 to have room for initialCapacity elements
        elements = new Object[initialCapacity + 1];
    }

    public void addFront(E elem) {
        checkCapacity();
    
        if (front == 0) {
            front = elements.length - 1;
        } else {
            front--;
        }
        
        elements[front] = elem;
    }

    public void addBack(E elem) {
        checkCapacity();
        
        elements[back] = elem;

        if (back == elements.length - 1) {
            back = 0;
        } else {
            back++;
        }
    }

    // Makes sure the queue has room for one more element.
    private void checkCapacity() {
        boolean needToExpand;
        if (front == 0) {
            needToExpand = back == elements.length - 1;
        } else {
            needToExpand = back == front - 1;
        }
        if (needToExpand) {
            Object[] newElements = new Object[elements.length * 2];
            if (front <= back) {
                int size = back - front;
                System.arraycopy(elements, front, newElements, 0, size);
                front = 0;
                back = size;
            } else {
                int numberOfElementsToCopyFirst = elements.length - front;
                System.arraycopy(elements, front, newElements, 0, numberOfElementsToCopyFirst);
                System.arraycopy(elements, 0, newElements, numberOfElementsToCopyFirst, back);
                front = 0;
                back = numberOfElementsToCopyFirst + back;
            }
            elements = newElements;
        }
    }

    /** Gets the ith element counted from the front without removing it. */
    public E get(int i) {
        int index = front + i;
        if (index >= elements.length) {
            index -= elements.length;
        }
        boolean outOfRange;
        if (front <= back) {
            outOfRange = index < front || index >= back;
        } else {
            outOfRange = index >= back && index < front;
        }
        if (outOfRange) {
            throw new ArrayIndexOutOfBoundsException(i);
        }
        return getInternal(index);
    }

    @SuppressWarnings("unchecked")
    private E getInternal(int index) {
        return (E) elements[index];
    }

}
公共类MyArrayDeque{
私有对象[]元素;
//索引到第一个元素。
专用int前端=0;
//索引到最后一个元素后的第一个可用空间。
//back==front表示队列为空(未满)。
私有int back=0;
公共MyArrayDeque(初始容量){
如果(初始容量<0){
抛出新的IllegalArgumentException(“初始容量不得为负”);
}
//始终至少有1个可用空间,因此添加1可为initialCapacity元素留出空间
元素=新对象[初始容量+1];
}
公共空白地址(E元素){
检查容量();
如果(前==0){
前=元素。长度-1;
}否则{
前面--;
}
元素[前]=元素;
}
公共无效回拨(E元素){
检查容量();
元素[返回]=元素;
if(back==elements.length-1){
后退=0;
}否则{
back++;
}
}
//确保队列有空间容纳一个或多个元素。
专用空校验容量(){
布尔需要扩展;
如果(前==0){
needToExpand=back==elements.length-1;
}否则{
needToExpand=后==前-1;
}
如果(需要扩展){
Object[]newElements=新对象[elements.length*2];
if(前=元素长度){
索引-=元素长度;
}
布尔超出范围;
如果(前=后);
}否则{
outOfRange=索引>=后和索引<前;
}
如果(超出范围){
将新的ArrayIndex抛出BoundsException(i);
}
返回getInternal(索引);
}
@抑制警告(“未选中”)
私有E getInternal(int索引){
返回(E)元素[索引];
}
}
要进行简单演示,请执行以下操作:

    MyArrayDeque<String> queue = new MyArrayDeque<>(1);
    
    queue.addFront("First element added");
    queue.addBack("Added at back");
    queue.addFront("Added at front");
    
    System.out.println(queue.get(1));
MyArrayDeque队列=新的MyArrayDeque(1);
queue.addFront(“添加的第一个元素”);
queue.addBack(“添加在后面”);
queue.addFront(“在前面添加”);
System.out.println(queue.get(1));
输出为:

添加了第一个元素

没有

我浏览了
ArrayDeque
的源代码,没有一个方法可以通过索引访问任意数组元素。这是在O(1)中执行操作所必需的

不过,实现自己的类来满足您的需求应该不会太难。搜索“循环缓冲区”。如果数组溢出,请将整个内容复制到一个新的大小为两倍的数组中。当然,这不能在固定时间内完成,但添加仍将在摊销固定时间内完成,与
ArrayDeque
相同

我假设
get()
的意思是通过从前面或后面计数的队列中元素的位置/索引来检查(不删除)元素

编辑

我想另一种方法是使用数组并找到一种方法 时间是恒定的,但我不知道怎么做

这是一个简单的实现。请根据您的需要进一步开发。其想法是使用循环缓冲区,如果旧的数组太小,则复制到新数组。我相信
ArrayDeque
使用了相同的想法

public class MyArrayDeque<E> {

    private Object[] elements;
    
    // Index to first element.
    private int front = 0;
    // Index to first free space after last element.
    // back == front means queue is empty (not full).
    private int back = 0;
    
    public MyArrayDeque(int initialCapacity) {
        if (initialCapacity < 0) {
            throw new IllegalArgumentException("Initial capacity must not be negative");
        }
        // There’s always at least 1 free space, so add 1 to have room for initialCapacity elements
        elements = new Object[initialCapacity + 1];
    }

    public void addFront(E elem) {
        checkCapacity();
    
        if (front == 0) {
            front = elements.length - 1;
        } else {
            front--;
        }
        
        elements[front] = elem;
    }

    public void addBack(E elem) {
        checkCapacity();
        
        elements[back] = elem;

        if (back == elements.length - 1) {
            back = 0;
        } else {
            back++;
        }
    }

    // Makes sure the queue has room for one more element.
    private void checkCapacity() {
        boolean needToExpand;
        if (front == 0) {
            needToExpand = back == elements.length - 1;
        } else {
            needToExpand = back == front - 1;
        }
        if (needToExpand) {
            Object[] newElements = new Object[elements.length * 2];
            if (front <= back) {
                int size = back - front;
                System.arraycopy(elements, front, newElements, 0, size);
                front = 0;
                back = size;
            } else {
                int numberOfElementsToCopyFirst = elements.length - front;
                System.arraycopy(elements, front, newElements, 0, numberOfElementsToCopyFirst);
                System.arraycopy(elements, 0, newElements, numberOfElementsToCopyFirst, back);
                front = 0;
                back = numberOfElementsToCopyFirst + back;
            }
            elements = newElements;
        }
    }

    /** Gets the ith element counted from the front without removing it. */
    public E get(int i) {
        int index = front + i;
        if (index >= elements.length) {
            index -= elements.length;
        }
        boolean outOfRange;
        if (front <= back) {
            outOfRange = index < front || index >= back;
        } else {
            outOfRange = index >= back && index < front;
        }
        if (outOfRange) {
            throw new ArrayIndexOutOfBoundsException(i);
        }
        return getInternal(index);
    }

    @SuppressWarnings("unchecked")
    private E getInternal(int index) {
        return (E) elements[index];
    }

}
公共类MyArrayDeque{
私有对象[]元素;
//索引到第一个元素。
专用int前端=0;
//索引到最后一个元素后的第一个可用空间。
//back==front表示队列为空(未满)。
私有int back=0;
公共MyArrayDeque(初始容量){
如果(初始容量<0){
抛出新的IllegalArgumentException(“初始容量不得为负”);
}
//始终至少有1个可用空间,因此添加1可为initialCapacity元素留出空间
元素=新对象[初始容量+1];
}
公共空白地址(E元素){
检查容量();
如果(前==0){
前=元素。长度-1;
}否则{
前面--;
}
元素[前]=元素;
}
公共无效回拨(E元素){
检查容量();
元素[返回]=元素;
if(back==elements.length-1){
后退=0;
}否则{
back++;
}
}
//确保
public E get(int i) {
    if (i < 0 || i > size()) {
        throw new ....("out of bounds");
    }
    long pos = this.head + i; 
    if (pos >= this.elements.length) {
        pos -= this.elements.length;
    }
    return this.elements[(int) pos];
}