最近在一本英文版数据结构书上看到这么一个Queue的实现(源码在最后),
有两个疑问:
1.enqueue方法中,我感觉有很多错误,不知道是不是作者在跟我开玩笑,特别是两个System.arraycopy的实现和tail的指向问题2.dequeue方法中,我觉得
if (size-- == 0) {
throw new NoSuchElementException();
}
这句话有问题,我觉得应该这么实现
if (size == 0) {
throw new NoSuchElementException();
}
size--;因为如果size=0的话,就会抛出异常,但是此时并没有让head+=1,也就是说,Queue对象里并没有减少一个元素
而原来的实现if (size-- == 0),这个时候size却减一了,这不是错了吗?我的问题问完了,如果我错了,请说出我错的理由,如果书上确实是写错了,请给出正确的代码来
这两种情况我都是会给分的.以下是这个类的源码:
package c07;import java.util.NoSuchElementException;public class Queue { protected Object[] data;
protected int size, head, tail; // Postcondition: this Queue object has been initialized.
public Queue() {
final int INITIAL_LENGTH = 100;
data = new Object[INITIAL_LENGTH];
size = 0;
head = 0;
tail = -1;// indicates initially empty queue
} // Postcondition: the number of elements in this Queue object has been
// returned
public int size() {
return size;
} // Postcondition: true has been returned if thie Queue object has no
// elements. Otherwise, false has been returned.
public boolean isEmpty() {
return size == 0;
} // Precondition: this Queue object is not empty. Otherwise,
// NoSuchElementException will be thrown.
// Postcondition: (a reference to ) the element at the front of
// this Queue object has been returned
public Object front() {
if (size == 0) {
throw new NoSuchElementException();
}
return data[head];
} // Postcondition: element has been inserted at the back of this Queue
// object. The averageTime(n) is constant, and
// worstTime(n) is O(n), but for n consecutive
// enqueues, worstTime (n) is still O(n).
public void enqueue(Object element) { if (size == data.length) {
// double the length of data
Object[] oldData = data;
data = new Object[data.length * 2]; // copy oldData[head...oldData.length-1] to
// data[0...oldData.length-1-head]
System.arraycopy(oldData, head, data, 0, oldData.length - head); if (head > 0) {
// copy oldData[0...tail] to data
// [head+1...oldData.length-1]
System.arraycopy(oldData, 0, data, head + 1, tail + 1);
} tail = (tail + 1) % data.length;
size++;
data[tail] = element;
} } // Precondition: this Queue object is not empty. Otherwise,
// NoSuchElementException will be returned.
// Postcondition: the front element has been removed from this Queue object
public Object dequeue() {
if (size-- == 0) {
throw new NoSuchElementException();
}
Object element = data[head];
head = (head + 1) % data.length;
return element;
}}
有两个疑问:
1.enqueue方法中,我感觉有很多错误,不知道是不是作者在跟我开玩笑,特别是两个System.arraycopy的实现和tail的指向问题2.dequeue方法中,我觉得
if (size-- == 0) {
throw new NoSuchElementException();
}
这句话有问题,我觉得应该这么实现
if (size == 0) {
throw new NoSuchElementException();
}
size--;因为如果size=0的话,就会抛出异常,但是此时并没有让head+=1,也就是说,Queue对象里并没有减少一个元素
而原来的实现if (size-- == 0),这个时候size却减一了,这不是错了吗?我的问题问完了,如果我错了,请说出我错的理由,如果书上确实是写错了,请给出正确的代码来
这两种情况我都是会给分的.以下是这个类的源码:
package c07;import java.util.NoSuchElementException;public class Queue { protected Object[] data;
protected int size, head, tail; // Postcondition: this Queue object has been initialized.
public Queue() {
final int INITIAL_LENGTH = 100;
data = new Object[INITIAL_LENGTH];
size = 0;
head = 0;
tail = -1;// indicates initially empty queue
} // Postcondition: the number of elements in this Queue object has been
// returned
public int size() {
return size;
} // Postcondition: true has been returned if thie Queue object has no
// elements. Otherwise, false has been returned.
public boolean isEmpty() {
return size == 0;
} // Precondition: this Queue object is not empty. Otherwise,
// NoSuchElementException will be thrown.
// Postcondition: (a reference to ) the element at the front of
// this Queue object has been returned
public Object front() {
if (size == 0) {
throw new NoSuchElementException();
}
return data[head];
} // Postcondition: element has been inserted at the back of this Queue
// object. The averageTime(n) is constant, and
// worstTime(n) is O(n), but for n consecutive
// enqueues, worstTime (n) is still O(n).
public void enqueue(Object element) { if (size == data.length) {
// double the length of data
Object[] oldData = data;
data = new Object[data.length * 2]; // copy oldData[head...oldData.length-1] to
// data[0...oldData.length-1-head]
System.arraycopy(oldData, head, data, 0, oldData.length - head); if (head > 0) {
// copy oldData[0...tail] to data
// [head+1...oldData.length-1]
System.arraycopy(oldData, 0, data, head + 1, tail + 1);
} tail = (tail + 1) % data.length;
size++;
data[tail] = element;
} } // Precondition: this Queue object is not empty. Otherwise,
// NoSuchElementException will be returned.
// Postcondition: the front element has been removed from this Queue object
public Object dequeue() {
if (size-- == 0) {
throw new NoSuchElementException();
}
Object element = data[head];
head = (head + 1) % data.length;
return element;
}}
应该是先判断if (size == 0)
然后才size--吧
所以应该没有什么影响
protected int size, head, tail; // Postcondition: this Queue object has been initialized.
public Queue() {
final int INITIAL_LENGTH = 100;
data = new Object[INITIAL_LENGTH];
size = 0;
head = 0;
tail = -1;// indicates initially empty queue
} // Postcondition: the number of elements in this Queue object has been
// returned
public int size() {
return size;
} // Postcondition: true has been returned if thie Queue object has no
// elements. Otherwise, false has been returned.
public boolean isEmpty() {
return size == 0;
} // Precondition: this Queue object is not empty. Otherwise,
// NoSuchElementException will be thrown.
// Postcondition: (a reference to ) the element at the front of
// this Queue object has been returned
public Object front() {
if (size == 0) {
throw new NoSuchElementException();
}
return data[head];
} // Postcondition: element has been inserted at the back of this Queue
// object. The averageTime(n) is constant, and
// worstTime(n) is O(n), but for n consecutive
// enqueues, worstTime (n) is still O(n).
public void enqueue(Object element) { if (size == data.length) {
// double the length of data
Object[] oldData = data;
data = new Object[data.length * 2]; // copy oldData[head...oldData.length-1] to
// data[0...oldData.length-1-head]
System.arraycopy(oldData, head, data, 0, oldData.length - head); if (head > 0) {
// copy oldData[0...tail] to data
// [head+1...oldData.length-1]
System.arraycopy(oldData, 0, data, head + 1, tail + 1);
}
}
tail = (tail + 1) % data.length;
size++;
data[tail] = element; } // Precondition: this Queue object is not empty. Otherwise,
// NoSuchElementException will be returned.
// Postcondition: the front element has been removed from this Queue object
public Object dequeue() {
if (size-- == 0) {
throw new NoSuchElementException();
}
Object element = data[head];
head = (head + 1) % data.length;
return element;
} public static void main(String[] args) {
Queue q = new Queue();
try {
q.dequeue();
} catch (NoSuchElementException e) {
System.out.println(e + " : q.size = " + q.size());
}
q.enqueue("1");
System.out.println(q.size());
}}
public void enqueue(Object element) { if (size == data.length) {
// double the length of data
Object[] oldData = data;
data = new Object[data.length * 2]; // copy oldData[head...oldData.length-1] to
// data[0...oldData.length-1-head]
System.arraycopy(oldData, head, data, 0, oldData.length - head); if (head > 0) {
// copy oldData[0...tail] to data
// [head+1...oldData.length-1]
System.arraycopy(oldData, 0, data, head + 1, tail + 1);
}
}
tail = (tail + 1) % data.length;
size++;
data[tail] = element; } 下次你這樣貼代碼吧,看得人都暈了...
它的思路是這樣的
1.如果隊列滿了
1).加長一倍
2).由head開始到length那段數據複制至新數組
3).若head不為0,接2)把head之前的數據複至新數組
2.將新元素放於隊尾
原书是这样的:
public void enqueue(Object element) { if (size == data.length) {
// double the length of data
Object[] oldData = data;
data = new Object[data.length * 2]; // copy oldData[head...oldData.length-1] to
// data[0...oldData.length-1-head]
System.arraycopy(oldData, head, data, 0, oldData.length - head); if (head > 0) {
// copy oldData[0...tail] to data
// [head+1...oldData.length-1]
System.arraycopy(oldData, 0, data, head + 1, tail + 1);
}
head = 0;
tail = oldData.length - 1;
}
tail = (tail + 1) % data.length;
size++;
data[tail] = element; }我少看了这两句话:
head = 0;
tail = oldData.length - 1;其实这个方法是一点问题也没有,呵呵
现在就剩第二个问题,在dequeue()方法中的
public Object dequeue() {
if (size-- == 0) {
throw new NoSuchElementException();
}
Object element = data[head];
head = (head + 1) % data.length;
return element;
}
如果我执行下面的代码的话,Queue里明明有一个元素的,可是size打印出来却是0
public static void main(String[] args) {
Queue q = new Queue();
try {
q.dequeue();
} catch (NoSuchElementException e) {
System.out.println(e + " : q.size = " + q.size());
}
q.enqueue("1");
System.out.println(q.size());
}