递归 - 具有 void 函数返回类型的反向 LinkedList

Posted

技术标签:

【中文标题】递归 - 具有 void 函数返回类型的反向 LinkedList【英文标题】:Recursion - Reverse LinkedList with void function return type 【发布时间】:2013-07-05 17:36:09 【问题描述】:

我试图使用递归来反转链表。我得到了解决方案,但无法解决在互联网上找到的以下问题。

使用递归反转链表,但函数应该有 void 返回类型。

我能够实现返回类型为 Node 的函数。以下是我的解决方案。

public static Node recursive(Node start) 

    // exit condition
    if(start == null || start.next == null)
        return start;

    Node remainingNode = recursive(start.next);

    Node current = remainingNode;

    while(current.next != null)
           current = current.next;

    current.next = start;
    start.next = null;
    return remainingNode;
 

我无法想象这个问题是否会有这样的解决方案。

有什么建议吗?

【问题讨论】:

向我们展示您的尝试。 为什么不用尾递归? 相当危险的实现,但对于练习来说还可以。递归通常在教学中使用很多,但如果您不知道最大递归深度,则不应在现实世界中使用递归。当深度取决于某些输入数据时,您很容易遇到 *** 错误。在大学或编程课程中通常会省略此细节。 【参考方案1】:

经过测试,它可以工作(假设您有自己的链表实现,其中 Nodes 知道 next 节点)。

public static void reverse(Node previous, Node current) 
    //if there is next node...
    if (current.next != null) 
        //...go forth and pwn
        reverse(current, current.next);
    

    if (previous == null) 
        // this was the start node
        current.next= null;
     else 
        //reverse
        current.next= previous;
       

你用它来称呼它

reverse(null, startNode);

【讨论】:

+1 表示良好的算法。但是,您应该为反向链表设置头节点。调用reverse(null, startNode);后startNode会和list的head一样,无法找到list的head。 tm99 确实有效。只是 startNode 现在是最后一个。检查此测试示例:pastebin.com/JxyDLHab 改为发布我的解决方案【参考方案2】:
public void recursiveDisplay(Link current)

        if(current== null)
           return ;
        recursiveDisplay(current.next);
        current.display();

【讨论】:

【参考方案3】:
static StringBuilder reverseStr = new StringBuilder();

public static void main(String args[]) 
    String str = "9876543210";
    reverse(str, str.length() - 1);


public static void reverse(String str, int index) 
    if (index < 0) 
        System.out.println(reverseStr.toString());
     else 
        reverseStr.append(str.charAt(index));
        reverse(str, index - 1);
        index--;
    

【讨论】:

【参考方案4】:

这应该可以工作

static void reverse(List list, int p) 
    if (p == list.size() / 2) 
        return;
    
    Object o1 = list.get(p);
    Object o2 = list.get(list.size() - p - 1);
    list.set(p, o2);
    list.set(list.size() - p - 1, o1);
    reverse(list, p + 1);

虽然要使用 LinkedList 高效,但应该将其重构为使用 ListIterator

【讨论】:

【参考方案5】:

我不熟悉Java,但这里有一个C++ 版本。反转列表后,仍然保留了列表的头部,这意味着仍然可以从旧的列表头部List* h访问该列表。

void reverse(List* h) 
    if (!h || !h->next) 
      return;
    
    if (!h->next->next) 
      swap(h->value, h->next->value);
      return;
    
    auto next_of_next = h->next->next;
    auto new_head = h->next;
    reverse(h->next);
    swap(h->value, new_head->value);
    next_of_next->next = new_head;
    h->next = new_head->next;
    new_head->next = nullptr;
  

【讨论】:

【参考方案6】:

试试这个代码 - 它确实有效

    public static ListElement reverseListConstantStorage(ListElement head) 
    return reverse(null,head);


private static ListElement reverse(ListElement previous, ListElement current) 

    ListElement newHead = null;
    if (current.getNext() != null) 
        newHead = reverse(current, current.getNext());
     else //end of the list
        newHead=current;
        newHead.setNext(previous);
    

    current.setNext(previous);        
    return newHead;        

【讨论】:

【参考方案7】:
public static Node recurse2(Node node)
    Node head =null;
    if(node.next == null) return node;
    Node previous=node, current = node.next;
    head = recurse2(node.next);
    current.next = previous;
    previous.next = null;
    return head;


调用函数时,返回值如下:

 list.head=recurse2(list.head);

【讨论】:

【参考方案8】:

下面的函数是基于 darijan 选择的答案,我所做的只是添加 2 行代码,以便它适合你们想要工作的代码:

public void reverse(Node previous, Node current) 
        //if there is next node...
        if (current.next != null) 
            //...go forth and pwn
            reverse(current, current.next);
        
        else this.head = current;/*end of the list <-- This line alone would be the fix
        since you will now have the former tail of the Linked List set as the new head*/


        if (previous == null) 
            // this was the start node
            current.next= null;
            this.tail = current; /*No need for that one if you're not using a Node in 
            your class to represent the last Node in the given list*/
         else 
            //reverse
            current.next= previous;
           
    

另外,我已将其更改为非静态函数,因此使用它的方式是:myLinkedList.reverse(null, myLinkedList.head);

【讨论】:

【参考方案9】:

这是我的版本 - void ReverseWithRecursion(Node currentNode) - 这是LinkListDemo类的方法,所以head是可访问的

    基本情况 - 如果 Node 为空,则不执行任何操作并返回。 如果 Node->Next 为 null,则“使其成为头部”并返回。

    其他情况 - 反转 currentNode 的 Next。

    public void ReverseWithRecursion(Node currentNode)
       if(currentNode == null) return;
       if(currentNode.next == null) head = currentNode; return;
    
       Node first = currentNode;
       Node rest = currentNode.next;
    
       RevereseWithRecursion(rest);
    
       first.next.next = first;
       first.next = null;
    
    

你这样称呼它-

LinkListDemo ll = new LinkListDemo(); // assueme class is available
ll.insert(1);  // Assume method is available
ll.insert(2);
ll.insert(3);
ll.ReverseWithRecursion(ll.head);

【讨论】:

【参考方案10】:

我能想到的最简单的方法是:

public static <T> void reverse( LinkedList<T> list )

    if (list.size() <= 1) 
        return;
    
    T first = list.removeFirst();
    reverse( list);
    list.addLast( first );

【讨论】:

请不要开玩笑。如果可以使用库LinkedList,为什么不使用Collection.reverse?如果您不使用该库,为什么不向我们展示addLast 的工作原理?请不要说你要遍历返回的列表。 @Icn 这只是一个递归练习。链表的实现不是本题的主题,我只以LinkedList为例。

以上是关于递归 - 具有 void 函数返回类型的反向 LinkedList的主要内容,如果未能解决你的问题,请参考以下文章

错误:在Java递归列表反向方法中“无法返回void结果”

不使用反向返回列表中最后一个元素的非尾递归函数?

为啥我无法在具有 void 返回类型的异步函数中捕获异常?

JPA 和 PostgreSQL:如何调用具有 void 返回类型的存储过程?

从函数中的 void * 参数返回数组

实体框架,具有返回类型的函数导入:无..返回 int?