递归地反转单链表

时间:2012-11-16 23:37:11

标签: list recursion linked-list

因此,基于此算法,我在计算机编程课程中有一部分可以反转单链接的节点列表

  

“按顺序遍历列表,删除每个节点并将其作为新的第一个节点插入。”

我能够迭代地做到这一点,但现在我的教授希望我们递归地做到这一点。 我正在尽力理解递归,但它不能很好地工作。

所以,我将编码从迭代改为我认为递归

private void recursiveReverse2(Node p)
{
    Node lead = p;
    Node tail = p;

    if (p == null)
    {
        return;
    }

    if (p.next == null)
    {
        return;
    }

    current = tail.next;
    lead = current.next;
    current.next = null;
    tail.next = lead;
    current.next = head;
    head = current;
    recursiveReverse2(tail);
}


public void reverse2()
{
    toggle();   //swithces sort of list from ascending-descending
    recursiveReverse2(head); //head initialized at start of class
}

基本上,我想问一下我实际做了什么递归。因为,recursiveReverse2()可以工作,但我只是不知道我是否实现了递归。

5 个答案:

答案 0 :(得分:1)

在编写递归时,通常最好考虑最终的情况,然后最后编写递归的情况。关于递归的另一件事是返回结果非常有用。

是的,您的解决方案在技术上是递归的,但我认为代码不起作用。在行current.next = head处,未定义head,除非此代码位于某些未显示的类中。更糟糕的是,它可能是无限循环,因为在函数的开头,tail = p并且最后使用tail调用递归,因此是无限循环。最好这将反转长度为3的列表,但不是任何长度的列表。

在Java中,递归函数通常需要一个“帮助”函数才能启动它。首先,假设以下节点类:

public class Node{
    public object data;
    public Node next;
}

鉴于问题陈述,我假设我们不允许使用数据指针,只是下一个指针。此代码将是除Node之外的其他类。

public Node recursiveReverse(Node p)
{
    return helperReverse(p, null);
} 

private Node helperReverse(Node p, Node previous)
{
    if (p == null)
    {
        return p;
    }
    else if (p.next == null)
    {
        p.next == previous;
        return p;
    }
    else
    {
        Node next = p.next;
        p.next = previous;
        return helperReverse(next, p);
    }
}

如果将它合并到Node类中,它会变得更好。

public class Node{
    public object data;
    public Node next;

    public Node reverse() {
        return reverse1(null);
    } 

    private Node reverse1(Node previous) {
        if (next == null) {
            next == previous;
            return this;
        }
        else {
            Node other = next;
            next = previous;
            return reverse1(other, this);
        } 
    }

}

享受!

答案 1 :(得分:0)

C ++中的循环代码假设您有一个具有下一个指针的节点类.... 两个函数首先调用递归函数,第二个递归函数反转单链表

 void callReverse()
 {
  node *tempPointer=head;
  head=NULL;
  reverse(tempPointer);
 }

第二个函数是递归函数

 void reverse(node * pointer)
 {

  if(pointer->next==NULL)   //this case works only when linked list has a single node
  {
    if(head==NULL)
     head=pointer; 
  }

  else if(pointer->next->next!=NULL)
  {
    reverse(pointer->next)  //recursive call
  }

  if(head==NULL)
   head=pointer->next;

  pointer->next->next=pointer;

  pointer->next=NULL;

 }

请给我你的建议......

答案 2 :(得分:0)

这个怎么样:

void driver(Node head)
{
    rec_rev_ll(head,NULL); 
}

void rec_rev_ll(Node head, Node prev) 
{
    Node tmp = head->next;
    if(tmp == NULL) // Ends recursion when end of linked list is reached.
    {
        head->next = prev;
        return;
    }
    head->next = prev;
    rec_rev_ll(tmp,head);
}

简短又甜蜜。

答案 3 :(得分:0)

在不使用任何临时节点的情况下反转列表:

struct node* reverse_helper(struct node *ptr, struct node **head)
{
        if(ptr->next == NULL)
            *head = ptr;
        else 
            (reverse(ptr->next,head))->next = ptr;

        return ptr;
}        

/*Call reverseList Function with your List head reference */
void reverseList(struct node **head)
{
     struct node *ptr = reverse_helper(*head,head);
     ptr->next = NULL;     
}

答案 4 :(得分:0)

void recursiveReverse(struct node** head_ref) { struct node* first; struct node* rest;

/* empty list */
if (*head_ref == NULL)
   return;  

/* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref; 
rest  = first->next;

/* List has only one node */
if (rest == NULL)
   return;  

/* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next  = first; 

/* tricky step -- see the diagram */
first->next  = NULL;         

/* fix the head pointer */
*head_ref = rest;             

}

解释

此处指针first和next对于每个interanl调用都是本地的。在stackeach time函数调用本身时,现在在堆栈上创建的两个临时指针* first是链接列表的前面元素,而* rest是指向链接列表上的下一个元素的指针。在每个调用网传递给递归意味着第二个元素指针被传递。最后,如果在堆栈中开始(rest == NULL)堆栈展开,则没有元素离开。在堆栈中,展开* rest forward将指向低级*第一个指针,这在退绕期间简单地将指针从一个堆栈反转到另一个堆栈。在初始*首先成为最后一个元素,所以它的下一个被改为null以防止非法引用first->next = NULL