在学61B时, 有个错误, 让我的强迫症狠狠地犯了, 毕竟就差那么一点点
而这个错误小到只是两个语句的顺序调换, 我却花了近两小时寻找...
然而这个错误却至关重要!
Autograder报错如下
乍一看这是get()函数的报错, 我反复思索也觉得我的get()函数应该没问题, 都有点怀疑人生了
public T get(int index) {
if (index < 0 || index >= size) {
return null;
}
return data[(start + index) % data.length];
}
事实上确实没问题...
而是我addLast和removeLast函数出了问题
原代码
public void addFirst(T item) {
if (size == data.length) {
// resize();
System.out.println("Deque is full");
return;
}
start = start == 0 ? data.length - 1 : start - 1;
data[start] = item;
size++;
}
public void addLast(T item) {
if (size == data.length) {
// resize();
System.out.println("Deque is full");
return;
}
end = (end == data.length - 1) ? 0 : end + 1;
data[end] = item;
size++;
}
public T removeFirst() {
if (isEmpty()) {
System.out.println("Empty Deque");
return null;
}
T result = data[start];
start = (start == data.length - 1) ? 0 : start + 1;
size--;
return result;
}
public T removeLast() {
if (isEmpty()) {
System.out.println("Empty Deque");
return null;
}
T result = data[end];
end = (end == 0) ? data.length - 1 : end - 1;
size--;
return result;
}
正确实现
public void addFirst(T item) {
if (size == data.length) {
// resize();
System.out.println("Deque is full");
return;
}
start = start == 0 ? data.length - 1 : start - 1;
data[start] = item;
size++;
}
public void addLast(T item) {
if (size == data.length) {
// resize();
System.out.println("Deque is full");
return;
}
data[end] = item;
end = (end == data.length - 1) ? 0 : end + 1;
size++;
}
public T removeFirst() {
if (isEmpty()) {
System.out.println("Empty Deque");
return null;
}
T result = data[start];
start = (start == data.length - 1) ? 0 : start + 1;
size--;
return result;
}
public T removeLast() {
if (isEmpty()) {
System.out.println("Empty Deque");
return null;
}
end = (end == 0) ? data.length - 1 : end - 1;
T result = data[end];
size--;
return result;
}
diff一下
出错原因
start和end二者关系没有明确, 一开始我以为start是头节点的索引, 而end是尾节点的索引
两种可行的解决方法
- 一种方法是start为头节点索引, end为尾节点下一个的索引
- 还有一种方法是start为头节点上一个索引, end为尾节点的索引
这样插入或删除节点时, 更新节点的顺序就比较清晰了
为什么是这样呢?
只需讨论插入第一个节点的情况就可以知道:
倘若以一开始错误的想法, 在插入一个节点后, start或end中的一个必会移动(分离)
但是按照原来的规定, start和end应该在同一索引(插入的节点), 插入第二个节点才需要分离
当然对插入第一个节点进行特殊处理也是可行的, 或者特殊初始化start和end亦可
但我觉得有些麻烦, 降低代码可读性
我傻了, 其实课上有提示