1

ねえ、私は現在、私のDoublyLinkedListの逆のメソッドで立ち往生しています。逆の方法を除いて、すべてが(どういうわけか)正常に機能しています。エラーが発生していません-System.out.println(list.reverse())単に出力がありません。

助言がありますか?事前にどうもありがとうございました。:)

わかりました:コードを編集しました。これまでのところ、すべてが正しく機能しています。ただし、再帰メソッドは、実際にリストを逆にするのではなく、単に同じ順序でリストを出力します。

更新されたコード:

public class DoublyLinkedStringList {

private String content;
private DoublyLinkedStringList prev;
private DoublyLinkedStringList next;

public DoublyLinkedStringList(String info) {
    content = info;
    prev = null;
    next = null;
}

private DoublyLinkedStringList(String content, DoublyLinkedStringList prev, DoublyLinkedStringList next) {
    this.content = content;
    this.prev = prev;
    this.next = next;
}

public DoublyLinkedStringList prepend(String info) {
    DoublyLinkedStringList newNode = new DoublyLinkedStringList(info);
    prev = newNode;
    newNode.next = this;

    return newNode;
}

public DoublyLinkedStringList delete(int index) {
    DoublyLinkedStringList curr = this;

    if (index == 0) {
        next.prev = null;
        return next;
    }

    for (int i = 0; i < index; i++) {
        curr = curr.next;
    }

    curr.prev.next = curr.next;
    if (curr.prev.next != null) {              
        curr.prev.next.prev = curr.prev;
    }
    return this;
}

public DoublyLinkedStringList reverse() {
    DoublyLinkedStringList currNode = this;

    while (currNode != null) {
        DoublyLinkedStringList temp = currNode.next;
        currNode.next = currNode.prev;
        currNode.prev = temp;

        if (currNode.prev != null) {
            currNode = currNode.prev;
        }
    }

    return this;
}

@Override
public String toString() {
    StringBuilder sb = new StringBuilder();

    for (DoublyLinkedStringList currNode = this; currNode != null; currNode = currNode.next) {
        sb.append(currNode.content);
        if (currNode.next != null) {
            sb.append(", ");
        }
    }
    return sb.toString();
}

public static void main(String argv[]) {
    DoublyLinkedStringList list = new DoublyLinkedStringList("Testliste");
    list = list.prepend("6");
    list = list.prepend("5");
    list = list.prepend("4");
    list = list.prepend("3");
    list = list.prepend("2");
    list = list.prepend("1");
    list = list.prepend("0");

    list = list.delete(1);
    System.out.println(list);

    list = list.reverse();
    System.out.println(list);
}

}

4

6 に答える 6

2

デザインで発生する問題の1つは、リストを逆にすると、ヘッドがテールになり、テールがヘッドになることです。しかし、クライアントは尻尾ではなく頭を指しています。この操作を100%正しく行ったとしても、クライアントが持っている参照を変更することはできません。あなたがしたいのは、オブジェクトとしてのリストの概念と、そのオブジェクトを構成するノードを分離することです(ノードはリストであり、その逆もあるため、現在、これら2つの概念を組み合わせています)。それらを分離することにより、リストへの参照は、リストの内容や順序などに関係なく常に同じになります。リストには先頭と末尾の参照が含まれ、ノードには次/前のみが含まれます。現在、リスト内のすべてのノードに頭と尻尾があり、そうでない場合は厄介なバグがポップアップする可能性があります。tヘッド/テールが変更されるたびに(つまり、先頭に追加、削除、または逆に)すべての参照を置き換えます。これらの2つのインスタンスを各ノードから移動した場合は、変更のリストに対してそれほど多くのメンテナンスを行う必要はありません。そうすれば、リバースを実装する方がはるかに簡単だと思います。

あなたのエラーはまさに私が言っている問題です。最後にこれを返します。クライアントが持っている参照は頭(つまりこれ)でした。ただし、すべてを繰り返して反転した後、頭が尾になっているので、これを返すことで新しい尾を返しました。そして、テールのtoString()は何もありません。

于 2012-12-16T19:48:12.727 に答える
1

通常、私はインターフェースを実装し、リストを逆にするためにIteratableを使用Iteratorしますが、現在のモデルに合わせてリビジョンを維持しました。変数に依存するように、とメソッドNodeの戻り値のタイプを変更しました。これで、リストは「反転」したときにリンケージを変更することはありませんが、変数と動作を介して逆の順序でトラバースされます。getNext()getPrev()forwardgetNext()getPrev()

コードへのIDEONEリンク

この編集を検討してください:

class DoublyLinkedStringList {

private Node head, tail;
boolean forward;

/**
 * Diese Klasse repraesentiert einen Knoten in der Doubly Linked List der
 * Klasse
 * <code>DoublyLinkedStringList</code>
 *
 */
private class Node {
    private String content;
    private Node next;
    private Node prev;

    public Node(String content) { this.content = content; }

    public Node(String content, Node next) {
        this.content = content;
        if(forward) { this.next = next; }                     //EDITED
        else        { this.prev = next; }                     //EDITED
    }

    public Node getNext() { return (forward) ? next : prev; } //EDITED
    public Node getPrev() { return (forward) ? prev : next; } //EDITED

    public void setNext(Node next) {
        if(forward) { this.next = next; }                     //EDITED
        else        { this.prev = next; }                     //EDITED
    }

    public void setPrev(Node prev) {
        if(forward) { this.prev = prev; }                     //EDITED
        else        { this.next = prev; }                     //EDITED
    }
}

public DoublyLinkedStringList() {
    this.head = null;
    this.tail = null;
}

public Node prepend(String info) {
    Node newNode = new Node(info);
    newNode.setPrev(null);
    newNode.setNext(getHead());
    if(newNode.getNext()!=null) { 
      newNode.getNext().setPrev(newNode);                     //EDITED
    } 
    if(forward) { head = newNode; }                           //EDITED
    else        { tail = newNode; }                           //EDITED
    if(getTail() == null) {                                   //EDITED
      if(forward) { tail = newNode; }                         //EDITED
      else        { head = newNode; }                         //EDITED
    }
    return head;
}

public Node delete(int index) {
    Node currNode = getHead();
    int count = 0;

    if (index == 0) {
        if(forward) { head = head.next; }                     //EDITED
        else        { tail = tail.prev; }                     //EDITED
        return head;
    }

    while (currNode != null) {
        if (count + 1 == index) {
            currNode.next.prev = currNode.prev; 
            currNode.prev.next = currNode.next;               //EDITED
            break;
        }
        currNode = currNode.getNext();                        //EDITED
        count++;
    }
    return currNode;
}

private Node next() {
    Node currNode = head;

    if (forward) {
        return currNode.getNext();
    } else {
        return currNode.getPrev();
    }
}

public Node getHead() { return (forward) ? head : tail; }     //EDITED
public Node getTail() { return (forward) ? tail : head; }     //EDITED
public DoublyLinkedStringList reverse() { forward = !forward; return this; }

@Override
public String toString() {
    StringBuilder sb = new StringBuilder();
    //EDITED LOOP STRUCTURE
    for (Node currNode = getHead(); currNode != null; currNode = currNode.getNext()) {
        sb.append(currNode.content);
        if (currNode.getNext() != null) {
            sb.append(", ");
        }
    }
    return sb.toString();
}

public static void main(String argv[]) {
    DoublyLinkedStringList list = new DoublyLinkedStringList();
    list.prepend("6");
    list.prepend("5");
    list.prepend("4");
    list.prepend("3");
    list.prepend("2");
    list.prepend("1");
    list.prepend("0");
    list.delete(3);
    System.out.println(list);
    System.out.println(list.reverse());
}
}
于 2012-12-16T21:37:29.127 に答える
0

これが私の解決策です。残念ながら、説明文を書く時間がありません。

public class DoublyLinkedStringList {
    private String info;
    private DoublyLinkedStringList prev;
    private DoublyLinkedStringList next;

public DoublyLinkedStringList(String pInfo)
{
    info = pInfo;
    prev = null;
    next = null;
}

private DoublyLinkedStringList(String pInfo, DoublyLinkedStringList pPrev, DoublyLinkedStringList pNext)
{
    info = pInfo;
    prev = pPrev;
    next = pNext;
}

public DoublyLinkedStringList prepend(String info)
{
    DoublyLinkedStringList n = new DoublyLinkedStringList(info);
    prev = n;
    n.next = this;

    return n;
}

public DoublyLinkedStringList delete(int index)
{   
    if (index == 0)
    {
        next.prev = null;
        return next;
    }

    DoublyLinkedStringList d = this;

    for (int i = 0; i<index; i++)
        d = d.next;

    // d is now the node which should be deleted

    // after delete(x) "next" schould be on pos x

    d.prev.next = d.next;   // take the next of the prev and set the new next to the next of d

    if (d.prev.next != null)    // if the next of d was not set to null, it must get to know his new prev (d's prev)
        d.prev.next.prev = d.prev;

    return this;
}


public DoublyLinkedStringList reverse() // moe or less less similar to my implementation in IntList.java
{
    DoublyLinkedStringList oldLast = getLast();
    next.reverse(this);
    prev = next;
    next = null;
    return oldLast;
}

public void reverse(DoublyLinkedStringList last)
{
    if (next != null)
        next.reverse(this);
    prev = next;
    next = last;
}

public DoublyLinkedStringList getLast()
{
    if (next == null)
        return this;
    return next.getLast();
}

@Override
public String toString()
{
    String r = "";

    for (DoublyLinkedStringList i = this; i != null; i = i.next)
    {
        r += i.info;
        if (i.next != null)
            r += ", ";
    }
    return r;
}

public String reverseToString() // uses prev; just for testing issues :)
{
    String r = "";

    for (DoublyLinkedStringList i = getLast(); i != null; i = i.prev)
    {
        r += i.info;
        if (i.prev != null)
            r += ", ";
    }
    return r;
}

public static void main(String argv[])
{
    DoublyLinkedStringList list = new DoublyLinkedStringList("Test");
    list = list.prepend("6");
    list = list.prepend("5");
    list = list.prepend("4");
    list = list.prepend("3");
    list = list.prepend("2");
    list = list.prepend("1");
    list = list.prepend("0");
    list = list.delete(1);
    System.out.println(list);
    System.out.println(list.reverseToString()+"\n");

    list = list.reverse();
    System.out.println(list);
    System.out.println(list.reverseToString());

    list = list.delete(6);
    list = list.delete(0);
    System.out.println(list);
    list = list.reverse();
    list = list.prepend("1");
    System.out.println(list);
}
于 2012-12-16T21:45:43.403 に答える
0

頭と尻尾も設定するだけです。その後、それは動作するはずです。しかし、さらなる改善のためにchubbsondubsの答えを参照してください!

于 2012-12-16T19:50:07.890 に答える
0

戻り型としてDoublyLinkedStringListがあるので、新しいオブジェクトを返したいと思います。この場合、オブジェクトを循環させ、prependすでに実装したメソッドを使用して新しいリストを作成することをお勧めします(いずれの場合も他のエラーがあります)。空のリストから始めて、元のオブジェクトをスキャンしながら、現在の要素を追加することができます。

それ以外の場合、リストを「インプレース」で反転する場合は、戻りvoid、最後の要素でヘッドを変更する必要があります。また、は二重リンクされているため、両方向にノードへのポインターがあるため、他のことを行う必要があります。

于 2012-12-16T19:58:19.227 に答える
0

逆の方法でこれを試してください。

public class DoublyLinkedList {
  Node first, current;
  boolean forward;
      //constructors... methods...

  private Node next() {
        if(forward) return current.next();
        else return current.previous();
  }

  public void reverse() {
    while(true) {
          if(next() == null) {
        first = current;
        forward = !forward;
        return;
      }
      current = next(); 
    }
  }
}
于 2012-12-16T19:59:07.710 に答える