[英]StackArray Generic class does not work
我是Java的初學者,正在嘗試編寫StackArray。 我有一個測試人員來測試我的代碼。 我已經運行了幾次,但它沒有通過我的push方法和我的搜索方法。 誰能告訴我我做錯了什么? 提前非常感謝您!
import java.util.Arrays;
import java.util.NoSuchElementException;
public class Stack<E> implements StackADT<E>{
private E a[];
private int head, size;
public Stack(){
}
/*Adds the specified element to the top of the stack.
Returns the item added.*/
public E push(E element){
if (a.length == size){
throw new IllegalStateException("Cannot add to full stack");
}
// Since the remainder of the stack is to the RIGHT of the stack,
// adding a new element pushes the head to the LEFT (+ wrap around)
//head = (head - 1 + a.length) % a.length;
return a[head++] = element;
// return element;
}
/*Removes and returns the element from the top of the stack*/
public E pop(){
if (empty()){
throw new java.util.EmptyStackException();
}
// We need to get a copy of the old head before we advance to the
// new head. We want to return the old head, not the new head.
E rval = a[head];
// Why DON'T we need to add a.length here like we did in push?
head = (head + 1) % a.length;
return rval;
}
/*Returns without removing the element at the top of the stack*/
public E peek(){
if (empty()){
throw new java.util.EmptyStackException();
}
return a[head];
}
/*Returns true if the stack is empty, false otherwise*/
public boolean empty(){
return size == 0;
}
/*Returns the 1-based position where an object is on this stack
This means If the object o occurs as an item in this stack, this
method returns the distance FROM THE TOP OF THE STACK of the
occurrence nearest the top of the stack - the topmost item on
the stack is considered to be at distance 1.*/
public int search(Object o){
// i is the LOGICAL index
for (int i = 0; i < size; i++){
// p is the PHYSICAL index
int p = (head + i) % a.length;
E e = a[p];
// e == o Are the items (null or non-null the same?)
// if they are not the same, then at least one of them
// is non-null and can be compared to the other.
if (e == o || e != null && e.equals(o)){
// Distance = logical index + 1 as per the above description
return i + 1;
}
}
// No match was made
throw new NoSuchElementException();
}
/*Returns a string representation of the queue*/
public String toString(){
// Output should look like: [e_0, e_1, ..., e_n-1]
// Empty stack: []
if (empty())
return "[]";
// We know that there is at least one element in this stack
// since we didn't return
StringBuilder b = new StringBuilder();
b.append("[").append(a[head]);
// Start on the SECOND logical index
for (int i = 1; i < size; i++){
int p = (head + i) % a.length;
E e = a[p];
b.append(", ").append(e);
}
b.append("]");
return b.toString();
}
}
最突出的錯誤是您沒有實例化Stack
的實例變量。 Java將默認值用於未初始化的值:原始數字設置為0
,布爾值設置為false
,所有引用類型(即數組和對象)都設置為null
。 這意味着head
和size
都初始化為0
而a
初始化為null
。 后者在取消引用其內容時會產生NullPointerException
。
假設要保留一個數組作為內部表示,則必須以某種方式初始化E[]
的實例。 不幸的是,您不能調用new E[size]
。 有關如何實例化通用數組,請參見另一個問題 。
至於head
的初始值(似乎應該指向堆棧的頂部),您在使用它的方式上不一致:在push
,您將head
用作a
下一個自由元素的索引並在添加元素后增加其值。 在toString
, peek
和pop
,將head
用作要返回的元素的索引。 兩種表示形式都可以,但是您不能將它們混淆。
假設你想head
總是指向最后一個元素,你將它初始化為-1
,並增加其在價值push
在訪問索引之前-方法a
。 注意head++
和++head
之間的區別:
int i = head++;
相當於
int i = head;
head = head + 1;
而
int i = ++head;
相當於
head = head + 1;
int i = head;
因此,您可以更改
return a[head++] = element;
至
return a[++head] = element;
但是最好增加幾行代碼,並通過先增加head
的值使邏輯更明確。
既然我們已經介紹了初始化,那么還有一個關於size
值的錯誤: push
應該增加棧的大小,而pop
應該減少棧的大小:但是,在您的代碼中, size
從未被修改,因此empty
始終為真。
另外,我不太明白這條線背后的想法
// Why DON'T we need to add a.length here like we did in push?
head = (head + 1) % a.length;
在pop
。 當元素被刪除(而不是添加)時,我想這應該是head = head - 1
或head--
如果您更喜歡postfix-operators。
正確初始化堆棧,例如,
private E a[];
private int head = -1;
private int size = 0;
public Stack(Class<E> c, int maxSize){
@SuppressWarnings("unchecked")
final E[] a = (E[]) Array.newInstance(c, maxSize);
this.a = a;
}
在push
中更新size
的值,並將更新固定為head
:
public E push(E element){
if (a.length == size){
throw new IllegalStateException("Cannot add to full stack");
}
size++;
return a[++head] = element;
}
更新size
的值並在pop
head
:
public E pop(){
if (empty()){
throw new java.util.EmptyStackException();
}
size--;
return a[head--];
}
備注:我有點忽略了注釋,因為隨着代碼的重構,注釋往往會撒謊; 但我只是注意到您在評論中寫道:
// Since the remainder of the stack is to the RIGHT of the stack,
// adding a new element pushes the head to the LEFT (+ wrap around)
這實際上與代碼的下一行相反: return a[head++] = element;
。 提出的錯誤修正基於代碼,而不是注釋,因此,堆棧的其余部分位於head
的LEFT處。 因此,必須更改toString
的實現才能從右到左而不是從左到右打印數組:
public String toString(){
if (empty())
return "[]";
StringBuilder b = new StringBuilder();
b.append("[").append(a[head]);
for (int i = head - 1; i >= 0; i--){
E e = a[i];
b.append(", ").append(e);
}
b.append("]");
return b.toString();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.