StackArray Generic类不起作用

时间:2014-12-02 01:28:55

标签: java arrays stack

我是Java初学者并尝试编写StackArray。我有一个测试人员来测试我的代码。我已经运行了好几次但它没有通过我的推送方法和我的搜索方法。谁能让我知道我做错了什么?非常感谢你!

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();
    }
}

1 个答案:

答案 0 :(得分:0)

最突出的错误是您没有实例化Stack的实例变量。 Java对非初始化值使用默认值:原始数字设置为0,布尔值设置为false,所有引用类型(即数组和对象)设置为null 。这意味着headsize初始化为0,而a初始化为null。后者在解除引用其内容时会产生NullPointerException

假设您想将数组作为内部表示,则必须以某种方式初始化E[]的实例。不幸的是,你不能打电话给new E[size]。有关如何实例化通用数组的信息,请参见 this other question

至于head的初始值,它似乎应该指向堆栈的顶部,你在如何使用它时并不一致:在push中,你使用head作为a中下一个自由元素的索引,并在添加元素后递增其值。在toStringpeekpop中,您使用head作为要返回的元素的索引。表示没问题,但你不能混淆它们。


假设您希望head始终指向最后一个元素,您需要将其初始化为-1并在push - 方法中增加其值,然后才能访问{{1}中的索引}}。请注意ahead++

之间的区别
++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; 中的

。当一个元素被删除(而不是添加)时,如果你更喜欢postfix-operators,我会说这应该只是pophead = head - 1

全部放在一起

正确初始化堆栈,例如

head--

更新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; } size的值,并将更新修正为push

head

更新public E push(E element){ if (a.length == size){ throw new IllegalStateException("Cannot add to full stack"); } size++; return a[++head] = element; } 中的sizehead的值:

pop

修复toString

备注:我忽略了这些评论,因为评论往往会在代码被重构时出现;但我刚注意到你在评论中写道:

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的实现,以便从右到左而不是从左到右打印数组:

toString