簡體   English   中英

StackArray通用類不起作用

[英]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 這意味着headsize都初始化為0a初始化為null 后者在取消引用其內容時會產生NullPointerException

假設要保留一個數組作為內部表示,則必須以某種方式初始化E[]的實例。 不幸的是,您不能調用new E[size] 有關如何實例化通用數組,請參見另一個問題

至於head的初始值(似乎應該指向堆棧的頂部),您在使用它的方式上不一致:在push ,您將head用作a下一個自由元素的索引並在添加元素后增加其值。 toStringpeekpop ,將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 - 1head--如果您更喜歡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--];
}

固定toString

備注:我有點忽略了注釋,因為隨着代碼的重構,注釋往往會撒謊; 但我只是注意到您在評論中寫道:

// 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM