当我调整数组大小时,我觉得有些问题,但是在我调整大小后队列没有正确排队。这是我已经完成的课程。
/**
* ArrayQueue
* Implementation of a queue using
* an array as the backing structure
*
* @author Your Name Here
* @version 1.0
*/
public class ArrayQueue<T> implements QueueADT<T> {
// Do not add instance variables
private T[] backing;
private int size;
private int front;
private int back;
/**
* Construct an ArrayQueue with an
* initial capacity of INITIAL_CAPACITY
*
* Use Constructor Chaining
*/
public ArrayQueue() {
backing = (T[]) new Object[INITIAL_CAPACITY];
size = 0;
front = 0;
back = 0;
}
/**
* Construct an ArrayQueue with the specified
* initial capacity of initialCapacity
* @param initialCapacity Initial capacity of the backing array.
*/
public ArrayQueue(int initialCapacity) {
backing = (T[]) new Object[initialCapacity];
size = 0;
front = 0;
back = 0;
}
@Override
public void enqueue(T data) {
if (data == null) {
throw new IllegalArgumentException("Data is null.");
}
//Resize
if (size >= backing.length) {
T[] backingCopy = (T[]) new Object[backing.length * 2];
for (int i = 0; i < backing.length; i++) {
backingCopy[i] = backing[i];
}
front = 0;
back = backing.length - 1;
backing = backingCopy;
}
backing[back] = data;
back = (back + 1) % backing.length;
size++;
}
@Override
public T dequeue() {
if (isEmpty()) {
throw new java.util.NoSuchElementException("Queue is empty.");
}
T returnData = backing[front];
backing[front] = null;
front = (front + 1) % backing.length;
size--;
return returnData;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
/**
* Returns the backing array for your queue.
* This is for grading purposes only. DO NOT EDIT THIS METHOD.
*
* @return the backing array
*/
public Object[] getBackingArray() {
return backing;
}
}
当我在调整大小后排队时,它会在前面而不是后面添加一些数字。
答案 0 :(得分:2)
您的实施存在一些问题:
一个。调整数组大小后,设置:
back = backing.length - 1;
应该是:
back = backing.length;
我们以容量为1的队列为例:
size
= 0
,front
= 0
,back
= 0
size
= 1
,front
= 0
,back
= 1 % 1
= 0
添加其他元素:size
== backing.length
一个。创建backingCopy
数组
湾将backing
个元素复制到backingCopy
数组
℃。 back
= backing.length - 1
= 1 - 1
= 0
d。设置backing
= backingCopy
即backing[back] = data
(这将覆盖索引0处的第一个添加元素)
B中。调整数组大小后将前置设置为0似乎是一个问题,除非您在复制到backingCopy数组时重新排序数据。
ArrayQueue:
public class ArrayQueue<T> {
private T[] backing;
private int size;
private int front;
private int back;
public ArrayQueue() {
backing = (T[])new Object[INITIAL_CAPACITY];
size = 0;
front = 0;
back = 0;
}
public ArrayQueue(int initialCapacity) {
backing = (T[]) new Object[initialCapacity];
size = 0;
front = 0;
back = 0;
}
public void enqueue(T data) {
if (data == null) {
throw new IllegalArgumentException("Data is null.");
}
if (size() == backing.length) {
resize();
}
backing[back] = data;
back = (back + 1) % backing.length;
size++;
}
private void resize() {
T[] backingCopy = (T[]) new Object[backing.length == 0 ? 1 : backing.length * 2];
// Insert elements from backing array to backingCopy in order.
System.arraycopy(backing, front, backingCopy, 0, backing.length - front);
System.arraycopy(backing, 0, backingCopy, backing.length - front, back);
front = 0;
back = backing.length;
backing = backingCopy;
}
public T dequeue() {
if (isEmpty()) {
throw new java.util.NoSuchElementException("Queue is empty.");
}
T returnData = backing[front];
backing[front] = null;
front = (front + 1) % backing.length;
size--;
return returnData;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size() == 0;
}
int front() {
return front;
}
int back() {
return back;
}
Object[] getBackingArray() {
return backing;
}
static final int INITIAL_CAPACITY = 100;
}
ArrayQueueTest:
import org.junit.Test;
import java.util.Arrays;
import java.util.NoSuchElementException;
import static org.junit.Assert.*;
public class ArrayQueueTest {
@Test
public void enqueue_withInitialCapacity0() {
// Given an ArrayQueue with initialCapacity 0.
int initialCapacity = 0;
ArrayQueue<Integer> q = new ArrayQueue<Integer>(initialCapacity);
// When enqueue is called.
q.enqueue(0);
// Then ArrayQueue resizes backing array to 1 and adds element.
assertEquals(Arrays.asList(0), Arrays.asList(q.getBackingArray()));
}
@Test
public void enqueue_lessThanCapacity() {
// Given an ArrayQueue with some initialCapacity.
ArrayQueue<Integer> q = new ArrayQueue<Integer>(2);
// When less than capacity elements are enqueued.
q.enqueue(0);
// Then ArrayQueue adds elements to backing array.
assertEquals(Arrays.asList(0, null), Arrays.asList(q.getBackingArray()));
}
@Test
public void enqueue_toCapacity() {
// Given an ArrayQueue with some initialCapacity.
ArrayQueue<Integer> q = new ArrayQueue<Integer>(2);
// When initialCapacity elements are enqueued.
q.enqueue(0);
q.enqueue(1);
// Then ArrayQueue adds elements to backing array.
assertEquals(Arrays.asList(0, 1), Arrays.asList(q.getBackingArray()));
}
@Test
public void enqueue_withResize() {
// Given an ArrayQueue is at capacity.
int initialCapacity = 2;
ArrayQueue<Integer> q = new ArrayQueue<Integer>(initialCapacity);
q.enqueue(0);
q.enqueue(1);
// When enqueue is called again.
q.enqueue(2);
// Then ArrayQueue is capacity is doubled and element is added.
int expectedCapacity = 2 * initialCapacity;
assertEquals(expectedCapacity, q.getBackingArray().length);
assertEquals(Arrays.asList(0, 1, 2, null), Arrays.asList(q.getBackingArray()));
}
@Test(expected = NoSuchElementException.class)
public void dequeue_isEmpty() {
// Given an empty ArrayQueue.
ArrayQueue<Integer> q = new ArrayQueue<Integer>();
// Throws when dequeue is called.
q.dequeue();
fail("Should have thrown NoSuchElementException.");
}
@Test
public void dequeue() {
ArrayQueue<Integer> q = new ArrayQueue<Integer>(4);
q.enqueue(0);
q.enqueue(1);
q.enqueue(2);
assertEquals(3, q.size());
assertEquals(0, q.front());
assertEquals(3, q.back());
assertEquals(Arrays.asList(0, 1, 2, null), Arrays.asList(q.getBackingArray()));
assertEquals(0, (int) q.dequeue());
assertEquals(2, q.size());
assertEquals(1, q.front());
assertEquals(3, q.back());
assertEquals(Arrays.asList(null, 1, 2, null), Arrays.asList(q.getBackingArray()));
assertEquals(1, (int) q.dequeue());
assertEquals(1, q.size());
assertEquals(2, q.front());
assertEquals(3, q.back());
assertEquals(Arrays.asList(null, null, 2, null), Arrays.asList(q.getBackingArray()));
assertEquals(2, (int) q.dequeue());
assertEquals(0, q.size());
assertEquals(3, q.front());
assertEquals(3, q.back());
assertEquals(Arrays.asList(null, null, null, null), Arrays.asList(q.getBackingArray()));
}
@Test
public void loopAround_enqueue() {
// Given an ArrayQueue with elements that have been dequeued.
ArrayQueue<Integer> q = new ArrayQueue<Integer>(4);
q.enqueue(0);
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
q.dequeue();
q.dequeue();
assertEquals(2, q.size());
assertEquals(2, q.front());
assertEquals(0, q.back());
assertEquals(Arrays.asList(null, null, 2, 3), Arrays.asList(q.getBackingArray()));
// When enqueue is called.
q.enqueue(4);
q.enqueue(5);
// Then resize is not called and elements are added to the front beginning of the array.
assertEquals(4, q.size());
assertEquals(2, q.front());
assertEquals(2, q.back());
assertEquals(Arrays.asList(4, 5, 2, 3), Arrays.asList(q.getBackingArray()));
}
@Test
public void loopAround_enqueue_withResize() {
// Given an ArrayQueue that loops around and is at capacity.
ArrayQueue<Integer> q = new ArrayQueue<Integer>(4);
q.enqueue(0);
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
q.dequeue();
q.dequeue();
q.enqueue(4);
q.enqueue(5);
assertEquals(Arrays.asList(4, 5, 2, 3), Arrays.asList(q.getBackingArray()));
// When enqueue is called.
q.enqueue(6);
// Then ArrayQueue resizes and reorders the backing array before adding the element.
assertEquals(5, q.size());
assertEquals(0, q.front());
assertEquals(5, q.back());
assertEquals(Arrays.asList(2, 3, 4, 5, 6, null, null, null), Arrays.asList(q.getBackingArray()));
}
@Test
public void loopAround_dequeue() {
ArrayQueue<Integer> q = new ArrayQueue<Integer>(4);
q.enqueue(0);
q.enqueue(1);
q.enqueue(2);
q.dequeue();
q.enqueue(3);
q.enqueue(4);
assertEquals(4, q.size());
assertEquals(1, q.front());
assertEquals(1, q.back());
assertEquals(Arrays.asList(4,1,2,3), Arrays.asList(q.getBackingArray()));
assertEquals(1, (int) q.dequeue());
assertEquals(3, q.size());
assertEquals(2, q.front());
assertEquals(1, q.back());
assertEquals(Arrays.asList(4, null, 2, 3), Arrays.asList(q.getBackingArray()));
assertEquals(2, (int) q.dequeue());
assertEquals(2, q.size());
assertEquals(3, q.front());
assertEquals(1, q.back());
assertEquals(Arrays.asList(4, null, null, 3), Arrays.asList(q.getBackingArray()));
assertEquals(3, (int) q.dequeue());
assertEquals(1, q.size());
assertEquals(0, q.front());
assertEquals(1, q.back());
assertEquals(Arrays.asList(4, null, null, null), Arrays.asList(q.getBackingArray()));
assertEquals(4, (int) q.dequeue());
assertEquals(0, q.size());
assertEquals(1, q.front());
assertEquals(1, q.back());
assertEquals(Arrays.asList(null, null, null, null), Arrays.asList(q.getBackingArray()));
}
}
答案 1 :(得分:1)
如果back < front
,您将错误地复制数组。您应该将front
复制到结尾,然后从开始复制到back
。
我没有测试过,但我认为这应该有效:
if (back < front) {
System.arraycopy(backing, front, backingCopy, 0, backing.length - front);
System.arraycopy(backing, 0, backingCopy, backing.length - front, back);
} else {
System.arraycopy(backing, 0, backingCopy, 0, backing.length);
}
此外,您必须将back
设置为backing.length
而不是backing.length - 1
。
答案 2 :(得分:-1)
仔细观察调整(复制)后备阵列后会发生什么......
最好还是考虑RingBuffer
- 您可以在Google上找到它