我正在尝试使用循环数组实现Deque这里是我的代码(抱歉发布整个类)
public class Deque<Item> implements Iterable<Item> {
private int frontIndex;
private int backIndex;
private static final int defaulSize = 8;
private int size;
private Item holder[];
private int capacity;
public Deque() {
holder = (Item[]) new Object[defaulSize];
this.size = 0;
this.frontIndex = 0;
this.backIndex = 0;
this.capacity = defaulSize;
}
public boolean isEmpty() {
return this.size == 0;
}
public int size() {
return this.size;
}
public void addFirst(Item item) throws Exception {
if (item == null) {
throw new NoSuchElementException();
}
if (size == capacity) {
doubleCapacity();
}
holder[this.frontIndex] = item;
this.frontIndex = Math.floorMod((this.frontIndex + 1), capacity);
size++;
}
public void addLast(Item item) throws Exception {
if (item == null) {
throw new NoSuchElementException();
}
if (size == capacity) {
doubleCapacity();
}
holder[this.backIndex] = item;
this.backIndex = Math.floorMod((this.backIndex - 1), capacity);
size++;
}
public Item removeFirst() throws Exception {
if (isEmpty()) {
throw new Exception("Deque is empty.");
}
this.frontIndex = Math.floorMod((this.frontIndex - 1), capacity);
this.size--;
Item e = holder[this.frontIndex];
holder[this.frontIndex] = null;
return e;
}
public Item removeLast() throws Exception {
if (isEmpty()) {
throw new Exception("Deque is empty.");
}
this.backIndex = Math.floorMod((this.backIndex + 1), capacity);
this.size--;
Item e = holder[this.backIndex];
holder[this.backIndex] = null;
return e;
}
private void doubleCapacity() {
int p = this.backIndex;
int n = holder.length;
int r = n - p; // number of elements to the right of p
capacity = (n) * 2;
Object[] a = new Object[capacity];
System.arraycopy(holder, p, a, 0, r);
System.arraycopy(holder, 0, a, r, p);
holder = (Item[]) a;
this.backIndex = n;
this.frontIndex = 0;
}
private class DequeIterator<E> implements Iterator<E> {
private int pos = 0;
public boolean hasNext() {
return holder.length > pos;
}
public E next() {
return (E) holder[pos++];
}
public void remove() {
throw new UnsupportedOperationException("Cannot remove an element of an array.");
}
}
@Override
public Iterator<Item> iterator() {
return this.new DequeIterator<Item>();
}
}
当我尝试使用deque调整圆形数组的大小时,问题就出现了,似乎所有索引都搞砸了
我使用的方法类似于在java实现中完成的实验
private void doubleCapacity() {
int p = this.backIndex;
int n = holder.length;
int r = n - p; // number of elements to the right of p
capacity = (n) * 2;
Object[] a = new Object[capacity];
System.arraycopy(holder, p, a, 0, r);
System.arraycopy(holder, 0, a, r, p);
holder = (Item[]) a;
this.backIndex = n;
this.frontIndex = 0;
}
如果将圆形数组用作deque,有没有特定的方法来调整圆形数组的大小,或者如何调整此deque的大小
(这不是家庭作业的个人研究)
答案 0 :(得分:1)
问题基本上是由于事实
1-在向Deque
添加项目时,您没有正确更新frontIndex和backIndex2-在容量加倍时不使用正确的索引。
问题1
当frontIndex和backIndex相等并且您在双端队列的任何入口点添加元素时,您需要更新它们,否则您将失去对Deque的控制权。示例:在开头,frontIndex和backIndex都是== 0。如果你添加一个项目让我们在前面说,之后你将有frontIndex = 1(正确)和backIndex = 0(不正确,因为位置0被新项目占用)。这有很多副作用
解决方案1
public void addFirst(Item item) throws Exception {
... unchanged handling of capacity...
holder[this.frontIndex] = item;
//CHECK OF THE 2 INDEXES
if(this.frontIndex==this.backIndex){
this.backIndex= floorMod((this.backIndex - 1), capacity);
}
this.frontIndex = floorMod((this.frontIndex + 1), capacity);
size++;
}
public void addLast(Item item) throws Exception {
... unchanged handling of capacity...
holder[this.backIndex] = item;
if(this.frontIndex==this.backIndex){
this.frontIndex= floorMod((this.frontIndex + 1), capacity);
}
this.backIndex = floorMod((this.backIndex - 1), capacity);
size++;
}
注意,删除功能中也存在问题,您应该正确处理。我没有时间处理它,但解决方案很简单
问题2
你总是使用backIndex(它在概念上可以)来处理新数组中项目的副本,但理想情况下backIndex指向之前的位置 Deque中的第一个元素,所以使用该值混乱迪克本身就多了一点。 您还要为 new backIndex分配完全错误的索引(它应该等于新创建的数组的最后一个元素的索引而不是n,这是指 old的大小数组)和frontIndex(应该等于位置n,即最后一个填充项目后的一个元素)。
解决方案2
private void doubleCapacity() {
int p = floorMod((this.backIndex+1 ), capacity);
int n = holder.length;
int r = n - p; // number of elements to the right of p
capacity = (n) * 2;
Object[] a = new Object[capacity];
System.arraycopy(holder, p, a, 0, r);
System.arraycopy(holder, 0, a, r, p);
holder = (Item[]) a;
//backIndex should be the last element of the whole array
this.backIndex = capacity-1;
//frontIndex must be 1 after the last element of the portio of array populated by items
this.frontIndex = n;
}
作为设计我将处理frontIndex和backIndex作为Deque中已经存在的第一个和最后一个元素的(循环)索引,而不是它们之前和之后的索引。但这只是我的方式。