Java 对于ArrayQue,有没有一种方法可以实现时间复杂度为O(1)的检索(get())?
我尝试将ArrayQue用于一个类,该类的addfront、addback和retrieval的时间复杂度应该是O(1)。我只能想到使用toArray()进行检索,不幸的是它是O(n)。有没有一种方法可以实现一个O(1)的ArrayQueue检索方法 我浏览了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)中执行操作所必需的 不过,实现满足您需求的自己的类应该不会太难。搜索“循环缓冲区”。如果数组溢出,请将整个内容复制到一个新的双倍大小的数组中。当然,这不能
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];
}