扭转双重链接列表

时间:2012-12-16 19:38:19

标签: java

嘿,我目前停留在我的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);
}

}

6 个答案:

答案 0 :(得分:2)

你的设计遇到的一个问题是当你颠倒列表时头部变成尾部而尾部成为头部。但客户指向头部,而不是尾部。即使您执行此操作100%更正,也无法更改客户端的引用。你要做的是将List的概念分离为一个对象,以及构成该对象的节点(目前你已将这两个概念结合在一起,因为节点是列表,反之亦然)。通过分离它们,列表的引用始终是相同的,无论其中包含什么,顺序等。列表包含头部和尾部引用,并且节点仅包含下一个/ prev。现在你在列表中的每个节点都有头部和尾部,如果你不改变头/尾的每个引用(即前置,删除或反转),就会弹出讨厌的错误。如果您将这两个实例移出每个节点,那么您不必对更改列表进行那么多维护。我想如果你这样做,那么你会发现实现逆转要容易得多。

你的错误正是我所说的问题。最后你回来了,客户端的参考就是头(即这个)。然而,在迭代并反转一切之后,头部现在是尾部,所以你通过返回它返回了新尾部。并且尾部的toString()没有。

答案 1 :(得分:1)

通常我会实现接口Iteratable并使用Iterator来反转列表但我保持我的修订版与您当前的模型一致。我将Node的{​​{1}}和getNext()方法的返回类型更改为依赖于getPrev()变量。现在,当“颠倒”时,列表永远不会更改链接,但是它会通过变量forwardgetNext()行为以相反的顺序遍历。

IDEONE link to code

考虑这个编辑:

getPrev()

答案 2 :(得分:0)

你只需设置头尾。那它应该工作。但是请看chubbsondubs的答案进一步改进!

答案 3 :(得分:0)

由于你有一个DoublyLinkedStringList作为返回类型,我想你想要返回一个 new 对象。在这种情况下,我建议你使用你已经实现的prepend方法遍历你的对象并构建一个新的List(任何一个都有其他错误)。您可以从空列表开始,并在扫描原始对象时添加当前元素。

否则,如果你想“反过来”列表,你应该返回void,用最后一个元素改变头部,并且由于是双重链接,你应该做任何其他事情,因为有指针到两个方向的节点。

答案 4 :(得分: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(); 
    }
  }
}

答案 5 :(得分: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);
}