【问题标题】:How to recursively print linked list in reverse by passing linked list reference as parameter [homework]如何通过将链表引用作为参数传递来反向递归打印链表[作业]
【发布时间】:2014-03-27 02:25:40
【问题描述】:

对于这个分配,我需要以链表作为参数,而不是节点,以递归方式反向打印链表。

我还必须使用我的教授提供的这个 SinglyLinkedList 类:

 public class SinglyLinkedList<E> {
  private int length; // # elements in the linked list
  private SLNode<E> head; // access point to the linked list
  private SLNode<E> tail;

  public SinglyLinkedList() {
    this.length = 0;
    this.tail = new SLNode<E> (); // the tail dummy node
    this.head = new SLNode<E> ( null, this.tail ); // the head dummy node
  }

  public int getLength() {
    return this.length;
  }

  public void add( E e ) {
    SLNode<E> newnode = new SLNode<E> ( e, null );
    newnode.setSuccessor( this.head.getSuccessor() );
    this.head.setSuccessor( newnode );
    this.length++;
  }

  public void add( E e, int p ) {
    // verify that index p is valid
    if ( ( p < 0 ) || ( p > this.length ) ) {
      throw new IndexOutOfBoundsException( "index " + p
                                           + " is out of range: 0 to " +
                                           this.length );
    }
    SLNode<E> newnode = new SLNode<E> ( e, null );
    SLNode<E> cursor = this.head;
    for ( int i = 0; i < p; i++ ) {
      cursor = cursor.getSuccessor();
    }
    addAfter( cursor, newnode );
    this.length++;
  }

  public E remove( int p ) {
    if ( ( p < 0 ) || ( p >= this.length ) ) {
      throw new IndexOutOfBoundsException( "index " + p
                                           + " is out of range: 0 to " +
                                           ( this.length - 1 ) );
    }
    SLNode<E> cursor = head; // good for p == 0
    if ( p > 0 ) {
      cursor = find( p - 1 ); // get target's predecessor
    }

    SLNode<E> target = cursor.getSuccessor(); // get the node to remove

    // link target to cursor's successor
    cursor.setSuccessor( target.getSuccessor() );
    target.setSuccessor( null );
    cursor.setElement( null );
    this.length--;
    return target.getElement();
  }

  public E getElementAt( int p ) {
    SLNode<E> node = this.find( p );
    return node.getElement();
  }

  private void addAfter( SLNode<E> p, SLNode<E> newnode ) {
    newnode.setSuccessor( p.getSuccessor() );
    p.setSuccessor( newnode );
  }

  private SLNode<E> find( E target ) {
    SLNode<E> cursor = head.getSuccessor();

    while ( cursor != tail ) {
      if ( cursor.getElement().equals( target ) ) {
        return cursor; // success
      }
      else {
        cursor = cursor.getSuccessor();
      }
    }
    return null; // failure
  }

  private SLNode<E> find( int p ) {
    if ( ( p < 0 ) || ( p >= this.length ) ) {
      throw new IndexOutOfBoundsException();
    }

    SLNode<E> cursor = head.getSuccessor();
    int i = 0;

    while ( i != p ) {
      cursor = cursor.getSuccessor();
      i++;
    }

    return cursor;
  }

}

我不知道如何通过传入对单链表而不是节点的引用来编写该方法。提前感谢您的帮助!

【问题讨论】:

  • 想一想——如果您遍历列表并边走边打印,您将以“前进”顺序打印列表。如果您将列表走到最后,然后向后追溯您的步骤,在每个向后的步骤上打印,您将以“反向”顺序打印列表。您可以通过递归调用“遍历”列表,然后返回是“倒退”。
  • 虽然我没有立即看到没有“遍历节点”的方法来做到这一点,而不是仅使用上述公共方法。似乎这样做的唯一方法是遍历列表(通过使用 elementAt 或在您行走时删除头节点)并在您行走时建立一个新列表,然后打印该新列表。
  • 打印过程中可以修改(销毁)列表吗?还是应该保留?
  • 我相信我可以在打印过程中修改列表。
  • @JustinBushy 不分析Hot Licks 刚才所说的,想想递归如何像堆栈一样(先调用后出)

标签: java


【解决方案1】:

基本情况是列表为空,没有可打印的内容。这就是我们首先检查的内容。如果满足基本情况,我们将返回而不打印任何内容。否则列表中还有剩余元素,因此我们从列表中取出最后一个元素(因为我们正在反向打印)并将其从列表中弹出。 remove 方法返回删除的元素,这样就可以解决问题。现在我们使用修改后的列表(减去最后一个元素)进行递归。最终列表将是空的,并且所有元素都将被反向打印。

public static <E> void printReverse(final SinglyLinkedList<E> list) {
    if(list.getLength() > 0) {
        System.out.println(list.remove(list.getLength()-1));
        printReverse(list);
    }
}

【讨论】:

    【解决方案2】:

    没有深入研究你的代码,但简单的打印应该很简单:

    在伪代码中:

    printLinkedListInReverse(node) {
       if (node has no next) {
           print out node itself
       } else {
           printLinkedListInReverse(node's next)
           print out node itself
       }
    }
    

    简而言之,要反向打印,您要先打印出不包括自身的剩余列表,然后打印节点本身


    如果抓不到内部节点,对链表进行修改,方法还是类似的:

    printLinkedListInReverse(list) {
       if (list is empty) {
           //do nothing
       } else {
           firstElement = list.remove(0)
           printLinkedListInReverse(list)  // print the remaining list first
           print firstElement
       }
    }
    

    【讨论】:

    • 我了解如何反向打印列表,并将节点引用作为参数传递。但是,我必须传入一个 SinglyLinkedList 引用。
    • 我以为您要将其添加为 SinglyLinkedList 的方法。如果你的代码无法访问内部节点,那么请看我的更新
    • 如果你想让列表看起来原样,你甚至可以先创建列表的副本并使用上面的方法,也可以将firstElement打印后放回列表的第一个位置
    猜你喜欢
    • 2021-11-30
    • 2013-06-02
    • 1970-01-01
    • 2014-07-30
    • 2018-07-11
    • 2011-12-19
    • 2013-03-04
    • 1970-01-01
    相关资源
    最近更新 更多