因此,基于此算法,我在计算机编程课程中有一部分可以反转单链接的节点列表
“按顺序遍历列表,删除每个节点并将其作为新的第一个节点插入。”
我能够迭代地做到这一点,但现在我的教授希望我们递归地做到这一点。 我正在尽力理解递归,但它不能很好地工作。
所以,我将编码从迭代改为我认为递归
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()可以工作,但我只是不知道我是否实现了递归。
答案 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