我正在尝试完全实现Deque而不使用已在java库中创建的Deque。我的代码编译,但输出并不像预期的那样。例如,应该将容量作为参数提供给类,但结果表明实际容量最终比指定的数量低1。
我遇到的另一个问题是队列应该作为先进先出。但这没有在结果中体现出来。任何想法?
public class ArrayDeque<E> implements IDeque<E> {
private int capacity;
private E[] array;
private int front;
private int end;
private int size;
public ArrayDeque(int capacity) {
this.array = (E[]) new Object[capacity];
this.capacity = capacity - 1;
front = 1;
end = 0;
size = 0;
}
private boolean isFull() {
return (size == capacity);
}
private boolean isEmpty() {
return (size == 0);
}
@Override
public int size() {
return size;
}
@Override
public void addFirst(E elem) throws DequeFullException {
if (isFull())
throw new DequeFullException("samlingen er full!");
array[front] = elem;
front = (front + 1) % capacity; // use modulo to make sure the front restarts from initial position once it reaches capacity
size++;
}
@Override
public E pullFirst() throws DequeEmptyException {
if (isEmpty())
throw new DequeEmptyException("Samlingen er tom!");
front = (front - 1) % capacity;
size--;
return array[front];
}
@Override
public E peekFirst() throws DequeEmptyException {
if (isEmpty())
throw new DequeEmptyException("samlingen er tom!");
System.out.println(array[(front - 1) % capacity]);
return array[(front - 1) % capacity];
}
@Override
public void addLast(E elem) throws DequeFullException {
if (isFull())
throw new DequeFullException("samlingen er full!");
array[end] = elem;
end = (end - 1) % capacity;
size++;
}
@Override
public E pullLast() throws DequeEmptyException {
if (isEmpty())
throw new DequeEmptyException("samlingen er tom!");
end = (end + 1) % capacity;
size--;
return array[end];
}
@Override
public E peekLast() throws DequeEmptyException {
if (isEmpty())
throw new DequeEmptyException("samlingen er tom!");
System.out.println(array[(end + 1) % capacity]);
return array[(end + 1) % capacity];
}
}
public class Main {
public static void main(String[] args){
ArrayDeque<String> deque = new ArrayDeque<>(6);
deque.addFirst("first");
deque.addFirst("second");
deque.addFirst("third");
deque.addFirst("fourth");
deque.peekFirst();
deque.peekLast();
deque.addLast("fourth");
deque.addLast("last");
deque.peekLast();
deque.size();
}
}
答案 0 :(得分:1)
关于您遇到的容量问题:
您正在设置阵列以使用户传递容量。这意味着例如用户输入6。现在,您将内部容量设置为容量-1,这意味着它将为5.现在,如果您使用较低容量执行模数,它会将位置设置为0,即使它可以在技术上将某些内容放入array[5]
。这是使用Arrays.toString运行的程序的打印,在每个addFront()之后打印您的数组:
[null, 0, null, null, null, null]
0
[null, 0, 1, null, null, null]
0
[null, 0, 1, 2, null, null]
0
[null, 0, 1, 2, 3, null]
0
[4, 0, 1, 2, 3, null]
0
[4, 5, 1, 2, 3, null]
5
这个问题的解决方案相当简单。将构造函数设置为如下所示:
public ArrayDeque(int capacity) {
this.array = (E[]) new Object[capacity];
this.capacity = capacity;
front = 1;
end = 0;
size = 0;
}
此外,考虑到您的FiFo问题: 您可能需要考虑更好地跟踪最后添加的元素以及应返回的元素。这可能会引入两个新的变量,但会让你的生活变得更加容易。例如:
public void addFirst(E elem) throws DequeFullException {
if (isFull())
throw new DequeFullException("samlingen er full!");
array[front] = elem;
first = front;
front = (front + 1) % (capacity); // use modulo to make sure the front restarts from initial position once it reaches capacity]
size++;
System.out.println(Arrays.toString(array));
}
假设first
是一个整数,在构造函数中设置为0。你可以随心所欲地做到这一点,但这可以更好地跟踪你的第一个元素。
另外,你的方法有点问题,考虑到你在一些数组中向后遍历一个数组,而没有考虑ArrayOutOfBoundsException
为-1的可能性。要解决这个问题,您可能希望从[0]
的结尾和[1]
的结尾切换到中间的起点。你必须找到一种放置和返回正确位置的方法,也许检查你用于遍历的变量是否等于0以及它是否转到数组的另一侧。像这样:
public E pullFirst() throws DequeEmptyException {
if (isEmpty())
throw new DequeEmptyException("Samlingen er tom!");
if(front == 0)
front = capacity;
front = (front-1) % (capacity);
size--;
return array[front];
}
使用main()中的代码生成以下输出:
public class Main {
public static void main(String[] args) {
ArrayDeque<Integer> arrDq = new ArrayDeque<>(6);
for(int i = 0; i < 6; i ++)
{
arrDq.addFirst(i);
}
for(int i = 0; i < 6; i ++)
{
System.out.println(arrDq.pullFirst());
}
}
}
输出:
[null, 0, null, null, null, null]
[null, 0, 1, null, null, null]
[null, 0, 1, 2, null, null]
[null, 0, 1, 2, 3, null]
[null, 0, 1, 2, 3, 4]
[5, 0, 1, 2, 3, 4]
5
4
3
2
1
0
为Deque的后部做同样的事情,它应该工作得很好。我希望这会有所帮助。