4

リンク リスト クラスの非常に簡単なメソッドを作成する必要がありますが、いくつか問題があります。と呼ばれるこのメソッドは、squish()このリストを取得し、( を使用して比較して) 2 つ以上の連続する項目が等しい場合equals()は、重複するノードを削除して、連続するコピーが 1 つだけ残るようにします。したがって、このリスト内の 2 つの連続する項目は、手順の完了時に等しくなりません。

実行後squish()、リストはsquish()開始時よりも短くなる可能性があります。削除されたものを補うために余分なアイテムが追加されることはありません。

たとえば、入力リストが の[ 0 0 0 0 1 1 0 0 0 3 3 3 1 1 0 ]場合、出力リストは[ 0 1 0 3 1 0 ]です。

これは私の方法です:

public void squish() {
 SListNode current = head;
 boolean end =false;

  while(end == false )
    {


      if(!current.item.equals(current.next.item))
          current=current.next;
      else
      {
          while(current.item.equals(current.next.item) && current.next !=null)
              current.next=current.next.next;
          current=current.next;

      }
    if (current==null)
        end=true;
    }


      }

これはコードを実行するための小さなメインです。

public class main {
public static void main(String args[])
{



    int[] test6 = {6, 6, 6, 6, 6, 3, 6, 3, 6, 3, 3, 3, 3, 3, 3};
    SList list6 = new SList();
    for (int i = 0; i < test6.length; i++) {
      list6.insertEnd(new Integer(test6[i]));
    }
    System.out.println("squishing " + list6.toString() + ":");
    list6.squish();
    String result = list6.toString();
    System.out.println(result);


    int[] test5 = {3, 7, 7, 7, 4, 5, 5, 2, 0, 8, 8, 8, 8, 5};
    SList list5 = new SList();
    for (int i = 0; i < test5.length; i++) {
      list5.insertEnd(new Integer(test5[i]));
    }

    System.out.println("squishing " + list5.toString() + ":");
    list5.squish();
    result = list5.toString();
    System.out.println(result);

}

}

コードをデバッグすると、メソッドが正常に機能することがわかります..リストの最後でのみ、null 例外ポインターを返します。手伝って頂けますか?ありがとう

4

3 に答える 3

4

問題は次の行にあります。

while(current.item.equals(current.next.item) && current.next !=null)

ここで、条件の最初の部分は、が null でcurrent.next.itemあっても にアクセスします。これは、条件の 2 番目の部分 ( ) が最初の部分のにチェックされるためです (最初の部分が に評価された場合のみ、以下を参照)。それを修正するには、条件を逆にするだけです。current.nextcurrent.next !=nulltrue

while(current.next !=null && current.item.equals(current.next.item))

このように、式は true の場合 (短絡評価)、つまり安全にcurrent.item.equals(current.next.item)実行できる場合にのみ実行されます。current.next !=null

ifまた、その最初のステートメントを削除できると思います。メソッドを単純化する方法については、@Pete の回答をご覧ください。

于 2013-07-15T20:40:48.097 に答える
4

私は次のようにします:

public void squish() {
    SListNode current = head; //1

    if(current = null) return;  //1a

    while(current.next != null) { //2
       if(current.item.equals(currennt.next.item))
          current.next = current.next.next;  //3
       else 
          current = current.next;  //4
    }
}

これは、専門家が再帰に割り当てるのが好きな種類のものです。ほとんどの専門家は再帰を使用しませんが、私はそのようにメソッドを設定しました。

1 行目は init です。リストをトラバースするポインターをリンクされたリストの先頭に割り当てます。

行 1a リストに要素がない場合は、戻ります。

ライン 2 は基本ケースです。リストに要素が 1 つしかない場合は、何もする必要はありません。

行 3 は、ノードを指している場合の誘導です。隣のノードを調べます。値が等しい場合は、隣のノードを削除できます。

4 行目は 3 行目の else です。隣のノードを調べたところ、等しくないことがわかりました。したがって、リストをトラバースします。

質問で提供されているテスト データを手動でトラバースし、私の例に System.out.println をいくつか追加して、正しいかどうかを確認するのは便利な練習になるかもしれません。何が起こっているのかを理解するために、今日はトリッキーなコードを使用してそれを行う必要がありました。

于 2013-07-15T20:36:34.770 に答える
2

if(!current.item.equals(current.next.item))最後の反復で行が実行されると、リストの最後の項目であるとしてcurrent.nextポイントされ、実際には次の項目はありませんnullcurrent

編集

NullPointerExceptionあなたのコメントで、私はあなたが列に並んでいるのを見ます

while(current.item.equals(current.next.item) && current.next !=null)

これらの 2 つの条件を互いに置き換えてcurrent.nextください。nullcurrentnext

while(current.next !=null && current.item.equals(current.next.item))

if(!current.item.equals(current.next.item))ところで、リストに要素が1つしかない場合でも、行にNPEが表示されます。たとえば、それを修正するには、 if head.next == null. whileその場合は、最初からループを開始しないでください。

于 2013-07-15T20:36:54.300 に答える