3

最近、私のクラスでは ArrayLists と LinkedLists を勉強しています。先週、LinkedList スタック クラス内に push メソッドと pop メソッドを作成するよう依頼された課題を受け取りました。後入れ先出しのようなスタックの背後にあるロジックは理解していますが、実際のコードに問題があります。私はコンピューター サイエンスを始めたばかりで (これは 2 回目のコースです)、この特定の割り当ては文字通り私の髪を引っ張る原因となっています。この課題はすでに提出済みですが、来週は中間試験があるので、うまくやりたいと思っています。私は助けを求めてウェブや教科書のいたるところにいましたが、何もありませんでした。私の教授は私を TA に紹介するだけで、TA は実際のコードではなく、ロジックを支援することにのみ関心があります。私の教授が私に与えた指示と、これまでの私のコードを以下に掲載します。

教授 より:

次の Java ファイルで指定されたテンプレートを使用してスタックを実装します。

CS401StackInterface.java CS401StackLinkedListImpl.java

public interface CS401StackInterface<E>
{
   /**
    * Get the top element on the stack.
    * 
    * @return the first element on the stack.
    */
   public E pop();

   /**
    * Adds an element on the top of the stack.
    * 
    * @param e - The element to be added to the stack.
    */
   public void push(E e);

   /**
    * Determines the number of elements in this data structure.
    * 
    * @return the number of elements currently resident in this
    *         data structure.
    */
   public int size();
}

メソッドを定義しようとする実際のクラスは次のとおりです。

public class CS401StackLinkedListImpl<E> implements CS401StackInterface<E> 
{
    private LinkEntry<E> head;
    private int num_elements;

    public CS401StackLinkedListImpl()
    {
        head = null;
        num_elements = 0;
    }

    public void setElement(LinkEntry<E> anElement){
        head = anElement;
    }

    /*Append the new element to the end of the list*/
    public void push(E e)
    {
        LinkEntry<E> temp = new LinkEntry<E>();
        temp.element = e;
        temp.next = head;
        head = temp;
    }

    /*Remove the most recently pushed element at the end of the list*/
    public E pop()
    {
        head.next = head;
        num_elements--;
        return (E) head;
    }

    public int size()
    {
        LinkEntry<E> temp = new LinkEntry<E>();
        for (temp = head; head != null; head = head.next)
            num_elements++;
        return num_elements;
    }

    public String toString()
    {
        String string = "";
        LinkEntry<E> temp = new LinkEntry<E>();
        for (temp = head; temp != null; temp = temp.next)
        {
            string += temp.element.toString() + "";
        }
        return string;
    }

/* ------------------------------------------------------------------- */
/* Inner classes                                                      */
    protected class LinkEntry<E>
    {
        protected E element;
        protected LinkEntry<E> next;

        protected LinkEntry() { element = null; next = null; }
    }
}

最後に、メソッドをテストするメイン クラスを次に示します。

import java.util.*;

public class App {

    public static <E> void main(String[] args) {

        CS401StackLinkedListImpl<String> my_stack = new CS401StackLinkedListImpl<String>();
        my_stack.push("Brian");
        my_stack.push("Chris");
        my_stack.push("Joe");
        System.out.println("Stack size: " + my_stack.size());
        my_stack.pop();
        System.out.println("Stack size: " + my_stack.size());
        my_stack.toString();
    }

}

メインクラスを実行すると、次のように返されます。

Stack size: 3
Exception in thread "main" java.lang.NullPointerException
    at week6.CS401StackLinkedListImpl.pop(CS401StackLinkedListImpl.java:30)
    at week6.App.main(App.java:66)

私が遭遇したものはすべて、新しいスタックを作成するように指示するだけです。これは、コードの「内部」について心配する必要がないため簡単ですが、それは私が必要としているものではありません。ありがとう。

4

4 に答える 4

2

問題はあなたのsize方法にあります。の値が壊れて、 になりheadますnull。次に、への呼び出しpopで NPE が取得されます。

変数の初期化にも問題があります -num_elementsを呼び出すたびに増加しますsize。への呼び出しで変数を増やすことで、これを単純化できますpush

また、次のポインターにパッチを適用せずに をsetElement設定するだけなので、使用するとスタックが破損します。head

申し訳ありませんが、これは宿題になっているようです...コードを修正する具体的な方法を次に示します。

public CS401StackLinkedListImpl()
{
    head = null;
    num_elements = 0;
}

public void setElement(LinkEntry<E> anElement)
{
    if (head != null)
        anElement.next = head.next; //New top-of-stack needs to point to next element, if any
    else
        anElement.next = null;
    head = anElement;
}

/*Append the new element to the end of the list*/
public void push(E e)
{
    LinkEntry<E> temp = new LinkEntry<E>();
    temp.element = e;
    temp.next = head;
    head = temp;

    num_elements++; // Increase number of elements count here
}

/*Remove the most recently pushed element at the end of the list*/
public E pop()
{
    E result = head.element; // Save return value of TOS
    head = head.next; // Corrected POP action
    num_elements--;
    return result;
}

public int size()
{
    //Remove below since count is kept accurate with push/pop methods
    //LinkEntry<E> temp = new LinkEntry<E>();
    //for (temp = head; head != null; head = head.next)
    //    num_elements++;
    return num_elements;
}

pop次のような要素がない場合は、追加のチェックインを追加して、NPE よりも優れた例外をスローすることができます。

if (head == null)
    throw new StackUnderflowException(); // and define a StackUnderflowException; or use a standard exception with a message
于 2012-10-05T19:56:07.660 に答える
0
public void push(E e)

大丈夫そうです。

public E pop()

うまくいかないようです。head.next要素自体に割り当てると、ループが作成されます。次に、実際の を返しますhead。最初に現在のヘッドをどこかに保存headしてから、次の要素への参照を更新し、前のヘッドを返す必要があります。

public int size()

メソッドが間違っています: まず最初に役に立たない要素をインスタンス化しますtempが、それは必要ありません (ループ内で temp を使用し、それを current に初期化する必要があるためheadです。次に、 for ループを確認してください:headどちらかを使用していますループ反復の終わりのどちらかの停止条件headリストを反復するだけで、それを変更するのではなく、 (正しいと思われるコードをtemp確認してください)だけなので、絶対に使用しないでください。toString

于 2012-10-05T19:49:50.033 に答える
0

コードを見ると、Pop メソッドが逆になっているようです。

push メソッドでは、現在のhead要素を新しい LinkEntry の「next」属性に割り当ててから、それを新しい head にします。したがって、リストからアイテムをポップするときは、「次の」要素をリストの先頭に割り当てる必要があります。あなたのコードは次のとおりです。

head.next = head;

次のようにする必要があります。

LinkEntry<E> toReturn = head;
head = head.next;
return toReturn.element;

実際には、スタックの一番上にある現在のアイテムへのヘッド参照を複製し(それを返すことができるように)、スタック内の次のアイテムを指すようにヘッド参照を移動します。

于 2012-10-05T19:53:42.150 に答える
0
/*Append the new element to the end of the list*/
public void push(E e)
{
    LinkEntry<E> temp = new LinkEntry<E>();
    temp.element = e;
    temp.next = head;
    num_elements++;//Increment count<--- Correction
    head = temp;
}

/*Remove the most recently pushed element at the end of the list*/
public E pop()
{
    E returnValue =head.element ;<--- Correction
    head=head.next;<--- Correction
    num_elements--;//Decrement count
    return  returnValue;
}

public int size()
{
   return num_elements;<--- Correction
}
于 2012-10-05T20:01:53.330 に答える