web-dev-qa-db-ja.com

Javaでの循環リンクリストの実装

これは課題です。循環リンクリストを作成し、リストの3つおきの番号を削除する必要があります。私のプログラムがリストの最後に到達すると、先頭に戻り、番号が1つだけになるまでプロセスを続行します。

オンラインやその他の参考書を検索しましたが、問題を解決できませんでした。私が見つけたほとんどの参照は次のようなことを言っています:

循環リストには終わりがないという事実を除けば、通常のリストとまったく同じです

または(教科書から引用):

最後のノードの後続ノードが最初のノードである場合、単一リンクリストは循環リンクされます

しかし、これらはそれを行う方法を教えていません。また、このサイトで見つけたコードを使用してみましたが、何も解決されませんでした。

リストを作成し(循環リンクリストであるかどうかはわかりません)、表示することはできますが、要素の順序は奇妙です。

  • リストに6つの数字がある場合、リストは1,6,5,4,3,2になります。
  • リストに8つの数値がある場合、リストは1,8,7,6,5,4,3,2になります。

正しいリストを取得しなくても、適切に削除できます。次のコードの何が問題になっています:

public class LastNumberDemo {
    public static void main(String[] args) {
        LastNumberNode ll=new LastNumberNode();
        System.out.println("how long is the list: ");
        Scanner keyboard = new Scanner(System.in);
        int input = keyboard.nextInt();

        if(input<=0) {
            System.out.println("no number to creat list");
        }
        if(input==1) {
            System.out.println("The Last number is 1.");
        }
        else {
            String[] n=new String[input];
            for(int index=0; index<n.length; index++)
                n[index]=Integer.toString(index+1);
            for(String e:n)
                ll.add(e);
            System.out.print("The list contains: \n");
            ll.print();
            System.out.print("\nThe last number is: ");
            ll.remove();
            ll.print();
        }
    }
}

//The circular linked list class
class LastNumberNode{
    private class Node{
        String value;  
        Node next;     

        Node(String val, Node n){
            value = val;
            next = n;
        }

        Node(String val){
            value=val;
            next=null;
        }
    } //This brace was missing - Edd

    private Node first;

    public LastNumberNode(){
      first = null;
    }

    public boolean isEmpty(){        
       return first == null;
    }

    public int size(){
        int count = 0;
        Node p = first.next;   
        while (p != first){
            count ++;
            p = p.next;
        }
        return count;
    }

    public void add(String e) {
        Node p=new Node(e);
        if(first==null){
            first=p;
            first.next=first;
        }
        else{
            first.next=new Node(e,first.next);
        }
    }

    public void remove(){
        while(size()>0){
            Node target=first.next.next;   
            Node temp=first;               
            target=target.next;          
            last.next=temp;
            first=target;
        }
    }

    public void print(){
        Node ref=first;
        for(int index=-1; index<size();index++)
            System.out.print(ref.value+" ");
        ref=ref.next;
    }
} //Extra brace removed - Edd
13
LPlateJava

新しいNodeをリストに追加すると、新しいNodeが2番目の位置に追加されます(_first.next_は新しく追加されたノードを指します)が、この新しく追加されたノードにはfirstを次のノードとして、残りのリストを参照せずに残します(したがって、ガベージコレクションされて破棄されます)。 addメソッドをそのまま使用すると、リストに0、1、または2のNodes以外を含めることはできません。リストの中央に新しいNodeを追加するのは少し奇妙です。それを前に追加するか(_newnode.next = first; first = newnode; last.next = first;_)、またはリストの後ろへの参照を保持し(他の人が提案したとおり)、そこに追加します。

個人的には、LastNumberNodeクラスを再構築して、リンクリストを操作するための次のメソッドを含めるようにします。

  • private void addNode(Node node)
  • private void removeNode(Node node)
  • private Node findNode(Node nextNode)

リストの最後のノードへの参照を維持する場合、addNode(Node node)メソッドは次のようになります。

_if(isEmpty()) {
    first = node;
    last = node;
}
else {
    Node tail = last;
    tail.next = node;
    node.next = first;
    last = node;
}
_

removeNode(Node node)は以下に基づいています:

_Node prevNode = findNode(node);

if(node == first) {
    first = node.next;
    last.next = first;
}
else if(node == last) {
    prevNode.next = first;
    last = prevNode;
}
else {
    prevNode.next = node.next;
}
_

これを実装する場合、おそらくこのようなアプローチを使用して、リストを単一のNodeに削減します。

_public String reduceList() {
    Node curNode = first;
    while(first != last) {
        removeNode(curNode.getNext().getNext());
        curNode = curNode.getNext().getNext();
    }

    return first.getValue();
}
_

最後のポイントとして、配列に連番を入力し、それを歩いて要素をリストに追加する手間を省きます。私は次のようなものにまっすぐ行きます:

_for(int i = 1; i <= input; i++) {
    linkedlist.add(new Integer(i).toString());
}
_
7
Edd

最初の要素が既に設定されている場合、addメソッドはfirstの直後に要素を挿入します。

first.next = new Node(e, first.next);

これは、観察された動作につながります。

リストの最後に新しい要素を追加する場合は、リストのlast要素を追跡し、新しい要素をlast.nextとして追加する必要があります。これを行う1つの方法は、リストクラスのメンバー変数の最後の要素への参照を保存することです。別の方法は、最後のノードであるfirstにリンクするノードが見つかるまでリストを走査することです。 。

4
l4mpi