2009-07-11 10 views
2

私は自分のリストシステムをJavaで実装しようとしています。ループに詰まっています

Listクラスファイル:

package RoutingDemo.List; 

/** 
* A 2-way Linked-List to store generic elements. 
* 
*/ 
public class List { 

    /* 
    Instance Variables 
    --------------------------------------------------------------------------- 
    */ 
    /** 
    * Reference to element. 
    */ 
    private Object info; 

    /** 
    * Reference to previous NodeList instance. 
    */ 
    private List prev; 

    /** 
    * Reference to next NodeList instance. 
    */ 
    private List next; 

    /* 
    Constructors 
    --------------------------------------------------------------------------- 
    */ 
    /** 
    * Creates a new empty list. 
    */ 
    public List() { 
     prev = null; 
     next = null; 
     info = null; 
    } 


    /* 
    Methods 
    --------------------------------------------------------------------------- 
    */ 
    /** 
    * Adds an element to the list. 
    * 
    * @param o Element to be added 
    */ 
    public List add(Object o) { 
     if(info == null) { 
       info = o; 
       prev = null; 
       next = null; 
       return this; 
     } else { 
       List temp = new List(); 
       temp.add(o); 

       return addList(temp); 
     } 
    } 


    /** 
    * Appends an existing list to this list. 
    * 
    * @param newList List to be appended 
    */ 
    public List addList(List newList) { 
     if(newList.info() == null) 
       return this; 

     List ref = this; 
     ref.last().setNext(newList.first()); 
     newList.first().setPrev(ref.last()); 

     return ref; 
    } 


    /** 
    * Get number of elements in the list. 
    * 
    * @return number of elements in list 
    */ 
    public int count() { 
     if(info == null) 
       return 0; 

     List ref = this.first(); 
     int count = 0; 

     while(true) { 
      count++; 
      if(!ref.isLast()) 
        ref = ref.next(); 
       else 
        break; 
     }   
     return count; 
    } 


    /** 
    * Deletes an element from the list. 
    * 
    * @param o Element to be deleted 
    * @return List which does NOT 
    * contain element o 
    */ 
    public List delete(Object o) { 
     if(info == null) 
       return this; 

     List ref = this.first();   

     while(true) { 
      if(ref.info() == o) { 
        if(ref.isFirst() && ref.isLast()) { 
          ref = new List(); 
          break; 
        } else if(ref.isFirst()) { 
          ref = ref.next(); 
          ref.killPrev(); 
          break; 
        } else if(ref.isLast()) { 
          /* *** THIS IS THE CASE THAT WILL BE CALLED FOR THIS TEST **** */ 
          ref = ref.prev(); 
          ref.killNext(); 
          break; 
        } else {    
          ref.prev().setNext(ref.next()); 
          ref.next().setPrev(ref.prev()); 
          ref = ref.prev(); 
          break; 
        } 
      } else { 
        if(!ref.isLast()) 
          ref = ref.next(); 
         else 
          break; 
      } 
     } 
     return ref; 

    } 


    /** 
    * Moves to first element in List. 
    * 
    * 
    * @return List pointing to first 
    * element in list 
    */ 
    public List first() { 
     List ref = this; 

     while(!ref.isFirst()) { 
      /* *** STUCK HERE *** */ 
      ref = ref.prev(); 
     } 

     return ref; 
    } 


    /** 
     * Returns current list element. 
     * 
     * @return current list element 
     */ 
    public Object info() { 
     return info; 
    } 


    /** 
    * Checks whether list is empty. 
    * 
    * @return true, if list is empty 
    * , false otherwise. 
    */ 
    public boolean isEmpty() { 
      if(count() > 0) 
        return false; 
       else 
        return true; 
    } 


    /** 
    * Checks whether current element is the first element. 
    * 
    * @return true, if current element is 
    * first element, false otherwise. 
    */ 
    public boolean isFirst() { 
     if(prev == null) 
       return true; 
      else 
       return false; 
    } 


    /** 
    * checks whether current element is the last element. 
    * 
    * @return true, if current element is 
    * last element, false otherwise 
    */ 
    public boolean isLast() { 
     if(next == null) 
       return true; 
      else 
       return false; 
    } 


    /** 
    * Cuts the list from next element. 
    * 
    * 
    * @param l new link for current element 
    */ 
    public void killNext() { 
     next = null; 
    } 


    /** 
    * Cuts the list from previous element. 
    * 
    * 
    * @param l new link 
    */ 
    public void killPrev() { 
     prev = null; 
    } 


    /** 
    * Moves to last element in List. 
    * 
    * 
    * @return List pointing to last 
    * element in list 
    */ 
    public List last() { 
     List ref = this; 

     while(!ref.isLast()) { 
      ref = ref.next(); 
     } 

     return ref; 
    } 


    /** 
    * Moves to next element in List 
    * 
    * 
    * @return List pointing to next 
    * element in list 
    */ 
    public List next() { 
     if(!isLast()) 
       return next; 
      else 
       return this; 
    } 


    /** 
    * Moves to previous element in List 
    * 
    * 
    * @return List pointing to previous 
    * element in list 
    */ 
    public List prev() { 
     if(!isFirst()) 
       return prev; 
      else 
       return this; 
    } 


    /** 
    * Sets the next link 
    * 
    * 
    * @param l new link for current element 
    */ 
    public void setNext(List l) { 
     next = l; 
    } 


    /** 
    * Sets the prev link for current element 
    * 
    * 
    * @param l new link 
    */ 
    public void setPrev(List l) { 
     prev = l; 
    } 
} 

そして、私はこのようにそれをテストしていた:私は最初の二つのノードを追加するとき

class Example { 
    Example() { 
     List nl = new List(); 
     nl = nl.add(new Node(5,6)); 
     System.out.println("" + nl.count()); 
     Node x = new Node(1,3); 
     nl = nl.add(x); 
     System.out.println("" + nl.count()); 
     nl = nl.delete(x); 
     System.out.println("as" + nl.count()); 

    } 
} 

public class ListTest { 
    public static void main(String args[]) { 
     new Example(); 
    } 
} 

今、すべてが正常です。しかし、私はcount()のノードに削除した後、無限ループに入ります。

多くのブレークポイントを通過した後、私は固まったコードの場所にマークを付けました。明らかに何かがdelete()関数で間違っている、私は間違って何をしているのか分からない。

当分の間、私はこれで私のdelete()コードに置き換えました:

public List delete(Object o) { 
    if(info == null) 
      return this; 

    List ref = this.first();   
    List temp = new List(); 

    while(true) { 
     if(ref.info() != o) 
       temp.add(ref.info()); 
     if(!ref.isLast()) 
       ref = ref.next(); 
      else 
       break; 
    } 

    return temp; 
} 

をしかし、これはメモリに優しい巨大なリストのことwouldntは。あなたが問題を発見できるかどうか教えてください!

+2

は、私はあなたがループ内で立ち往生しているごめんなさい!有益な洞察を得るには、この質問への回答をチェックしてください:http://stackoverflow.com/questions/1113769/stuck-in-a-loop-o –

+0

Don Branson ...そのリンクはこのページにリンクしています。 – Dykam

+0

@Dykam、あなたは賢い獣です。 –

答えて

3

問題は、あなたのリストが壊れてしまうことです。

  1. リスト{情報=ノード(5,6)、前= nullを、次= 2}
  2. リスト{:あなたは、リスト内の2つの項目を持っている時点で、それは次のようになります情報=ノード(1,3)、PREV = 2、次= NULL}

Woopsは、それ自体を指しているリストのフィールドの2番目の項目に気づきますか?あなたの問題は、この方法である:

その行に
public List addList(List newList) { 
    // ... 
    newList.first().setPrev(ref.last()); // <-- here 
} 

ref.last()リストの最後の項目、refを探してループする方法です。しかし、最後の項目は、前の行はこのようになりますので、あなたは、それがあることを期待するものではありません。

ref.last().setNext(newList.first()); 

何を見てみたいことは、それはあなたが設定前だっただろうと最後の項目がありますそれは次のフィールドで、最後に新しいリストを追加します。新しいリストが追加された後、しかし、再び最後メソッドを呼び出すことによって、あなたは、新しい最後の項目を見つけることです。だからこそ、最後のノードが自分自身を指しているのです。

はこのように見て、あなたの ADDLIST方法に変更

public List addList(List newList) { 
    if(newList.info() == null) 
        return this; 

    List ref = this; 
    List last = ref.last(); 
    last.setNext(newList.first()); 
    newList.first().setPrev(last); 

    return ref; 
} 

を...、それが動作します。リストを修正する前にリストを最後にキャッシュすることで、正しい参照ができます。

たとえそうだとしても、あなたのコードは、それがなければならないよりも、かなり複雑です。二重リンクされたリストを実装する方法の例を調べて、それをもっと簡単に行う方法を示す例を見つけてください。あなたのの削除メソッドは、あまりにも複雑すぎます。

また、nullを含むノードとして空のリストを表すことに問題があると思います。それはあなたがチェックする必要があるすべての種類の不快なケースを持っているように思われます。

+0

Aahはい。私は今、光を見る。 >。<ありがとうございました:) – Bojack

1

オブジェクトで==を使用している可能性があります。

if(ref.info() == o) 

あなたの無限ループの正確な問題ではない場合でも、対処する必要がある問題です。

+0

しかし、私は参考としてそれを比較することを意味します。 ListクラスをNodeListなどに拡張します。そして私はオブジェクトが参照によって比較される環境で作業しています。どのようなケアでも、私が保持している情報に関してオブジェクトを比較しなければならない場合、私はサブクラスのメソッドでそれを行います。 – Bojack

1

あなたのコードには、無限ループの可能性がたくさんあります。できるだけ多くの

while (someCondition) { 
    // do something interesting 
    // go forward in the loop 
} 

while (true) { 
    // do something interesting 
    if (someCondition) 
     // go forward in the loop 
    else 
     break; 
} 

のようなコードを書き換えるようにしてください。

また、必ずあなたのListの最後の要素のnextが戻ってあなたのListの最初の要素を指すことはありません、またはあなたが実際に長い時間のために円で走り回っていることでしょうことをことを確認します。

+0

私は知っています。 私もそのループ形式を使用して嫌いです。 私が条件を与えた場合、> while(!listObject.isLast()){このことを行い、増分}、最後の要素のコードも書き直す必要があります。 :) – Bojack

+0

あなたはどうしてそうだと思いますか? – jqno

0

あなたの問題はADDLISTである:

public List addList(List newList) { 
     if(newList.info() == null) 
         return this; 

     List ref = this; 
     //you should get a reference to the original "last" 
     ref.last().setNext(newList.first()); 
     newList.first().setPrev(ref.last()); 

     return ref; 
    } 

ではなく、次の操作を行います。

public List addList(List newList) { 
     if(newList.info() == null) 
         return this; 

     List ref = this; 
     List last = ref.last(); 
     last.setNext(newList.first()); 
     newList.first().setPrev(last); 

     return ref; 
    } 

をあなたは常にリストに2つ目の項目を追加し、それを自身の最後を作っていました。これにより、削除したときにはkillNextの操作しか実行されず、最初のノードは変更されません。 次に、自己参照するノードを呼び出し側の例に戻します。残りのリストと思われるものは参考にしてください。そのノード上でcount()を呼び出すとfirst()が呼び出され、!isFirst()は常に真となり、それは前回と同じように常に参照されていたので、ループはref = ref.prev();行で継続的に再集合します。

+0

それは働いた。 !ありがとうございました。しかし、私はあなたが言ったことに従うかどうかは分かりません。なぜ私はそれを変更する前にlast()を明示的に参照する必要があるのでしょうか? – Bojack

+0

hah。あなたは私がやったのとまったく同じ解決策を考え出しましたが、私にそれを打ち負かしました。それを見つけ出すのにうってつけです。 – IRBMe

+0

nice。私はそれをun-wonしたと思います;) – akf

0

私はJavaで私自身のリストのシステムを実装しようとしています。

私の提案は、しないでください。標準で動作する組み込みリストを再利用する必要があります。どのように動作しているか知りたい場合は、ソースを読むことができます。

自分自身を書く方法を知っているリストの実装はインタビューに役立つかもしれませんが、実際の仕事でこれを決してしないことを強くお勧めします。

+0

宿題とタグ付けされているので、おそらくこれは割り当てであり、何かではなく、組み込みクラスを使用できます。 –

+0

これはLinkedListのコードを少なくとも読み取ることができますが、これはこれに基づいているようです。 –

関連する問題