扭转链表

时间:2010-11-02 14:54:43

标签: c data-structures linked-list

我正在尝试使用递归来反转链接列表并为其编写以下代码。列表是开头的列表的开头。

 node *reverse_list_recursive(node *list)
 {
      node *parent = list;
      node *current = list->next;

      if(current == NULL)
       return parent;

      else
       {
           current = reverse_list_recursive(current);
           current->next = parent;
           printf("\n %d  %d \n",current->value,parent->value);
           return parent;
       }

  }

我可以看到所有链接都被颠倒了。然而,当我尝试显示时,我得到了数字的无限打印。当我试图反转列表中最初的第一个数字的链接时,我怀疑是错误的。

我做错了什么?

10 个答案:

答案 0 :(得分:5)

假设我有一个链表:

 ----------      ----------      ----------      ---------- 
|  1  |    |--->|  2  |    |--->|  3  |    |--->|  4  |    |--->NULL
 ----------      ----------      ----------      ---------- 

您的代码将其转换为:

   ----------------------          ----------------------
   |                    |          |                    |
   v                    |          v                    |
 ----------      ----------      ----------      ----------
|  1  |    |--->|  2  |    |    |  3  |    |    |  4  |    | 
 ----------      ----------      ----------      ---------- 
                   ^                    |
                   |                    |
                   ----------------------

请注意,第一个元素仍然指向2。

如果在前两个之后添加行parent->next = NULL,您将获得:

           ----------------------          ----------------------
           |                    |          |                    |
           v                    |          v                    |
         ----------      ----------      ----------      ----------
NULL<---|  1  |    |    |  2  |    |    |  3  |    |    |  4  |    | 
         ----------      ----------      ----------      ---------- 
                           ^                    |
                           |                    |
                           ----------------------

实际上是正确的结构。

完整的代码是:(您只需要为每个递归调用打印当前值)

node *reverse_list_recursive(node *list)
  {
      node *parent = list;
      node *current = list->next;

      if(current == NULL)
       return parent;

      else
       {
           current = reverse_list_recursive(current);
           parent->next = NULL;
           current->next = parent;
           printf("\n %d \n",current->value);
           return parent;
       }

  }

答案 1 :(得分:2)

您需要将新尾部(即旧头部)的下一个指针设置为NULL

编辑:这是一个递归版本

node *reverse_list_recursive(node *list)
  {
      node *parent = list;
      node *child = list->next;
      node *new_head;


    if (child == NULL)
          return parent ;  /* new head */

    new_head = reverse_list_recursive(child)
    child->next = parent; /* Old parent is the new child of the old child when reversed */
    parent->next = NULL; /* might be tail, will be overwritten after we return if we're not at the top level */
    return new_head;
}

答案 2 :(得分:2)

当您到达列表末尾时,将返回最后一个节点。然后,最后一个节点的下一个值被分配给自己,因此您会产生不一致。如果current为NULL,则返回NULL,如果返回为NULL,则忽略其余代码。

答案 3 :(得分:2)

您忘记更新链接列表中第一个项目的next成员。在递归调用之前添加parent->next = NULL;

答案 4 :(得分:2)

我没有看到递归的好处,迭代也会起作用。自从我编写C(并且没有简单的方法来测试以下语法错误......或者 cringe 核心转储,但你得到了这个想法)以来,它一直是永恒的。

node *reversed_list(node *list) {
    node *fwd=list;//Purely for readability
    node *last=null;
    node *next=null;
    node *rev=null;
    do {
        //Cache next
        next=fwd->next;
        //Set current
        rev=fwd;
        //Reset next to point back
        rev->next=last;
        //Update last
        last=fwd;
        //Forward ptr;
        fwd=next;
    } while (fwd!=null);
    return rev;
}

非常确定你的*list在调用之后没用,因为它现在指向列表的最后一个元素->next=null,可能只是更新它而不是返回指针。

更新(针对递归解决方案)

正如其他人所说,你的新尾巴搞砸了(指向最后一个元素,但应该指向null)......并且你没有返回正确的头部,你返回第二个元素。请考虑使用您的算法列表a->b->null

p=a,
c=b;
c=
   p=b
   c=null
   return b; //b->null
c=b
c->next=a //b->a
return a; //a->b, b->a, a returned
//But what you wanted is a->null, b->a, and b returned

以下更新的代码将会修复:

node *reverse_list_recursive(node *list)
  {
      node *parent = list;
      node *current = list->next;

      if(current == NULL)
       return parent;

      else
       {
           current = reverse_list_recursive(current);
           current->next = parent;
           parent->next=null; //Fix tail
           printf("\n %d  %d \n",current->value,parent->value);
           return current; //Fix head
       }

  }

使用列表a->b->null

p=a,
c=b;
c=
   p=b
   c=null
   return b; //b->null
c=b
c->next=a //b->a
p->next=null //a->null
return b; // b->a->null

答案 5 :(得分:1)

在行current = reverse_list_recursive(current);之后,您将新列表头存储在当前,因此current->next = parent;是错误的。新的current是新的列表头,但您需要访问新的列表尾部,即OLD current

node* newhead = reverse_list_recursive(current);
current->next = parent;
printf("\n %d  %d \n",current->value,parent->value);
return newhead;

答案 6 :(得分:1)

我可以看到的一些问题:

  • 你需要制作下一个指针 新的最后一个节点为NULL。
  • 如果我,你现有的功能会被打破 最初将NULL传递给它。

答案 7 :(得分:1)

这里是用于反转链表的递归代码。

list * reverse(list * head)
{
    if( head == NULL || head -> link == NULL )
        return head;
    list *node = reverse( head- > link );
    head -> link -> link = head;
    head -> link = NULL;
    return node;
}

答案 8 :(得分:0)

上面的Severl版本不能像OP那样工作,所以这里我的递归版测试很好:

node * reverseRecursive(node *p,node **head)
{
     if(p->next == NULL)
     {
         *head = p;
          return p;
     }
     node *before;
     before = reverseRecursive(p->next,head);
     before->next = p;
     p->next = NULL;
     return p;
}

//call from main
node*head; 
//adding value
//assuming now head is now 1->2->3->4->NULL
node* newHead;
reverseRecursive(head,&newHead);
//now now newHead is now 4->3->2->1->NULL

答案 9 :(得分:0)

不同的代码如下:

'

#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)

struct Node {
    int data;
    struct Node* next;
};
typedef struct Node node;

node* dogrusıralama(node* r)
{
    for (int i = 0; i < 6; i++)
    {
        printf("%d", r->data);
        r = r->next;
        printf("\n");
    }
}
node *terssıralama(node* r)
{
        node* iter;
        iter = r;
        node* temp;
        temp = r;
        node* temp2;
        temp2 = r;
        int a = 4;
        for (int k = 0; k < 5; k++)
        {        
            temp2 = temp2->next;
        }
        for (int j = 0; j < 5; j++)
        {
            int i = a;
            for (; i > 0; i--)
            {
                temp = temp->next;
        
            }
            a--;
            iter = temp;
            iter->next->next = iter  ;
            temp = r;
        }
        temp->next = NULL;
        return temp2;
}
int main() {
    node* dugum;
    node* dugum2;
    node* dugum3;
    node* dugum4;
    dugum = (node*)malloc(sizeof(node*));
    dugum2 = dugum;
    for (int i = 0; i < 5; i++)
    {
        dugum2->next = NULL;
        dugum2->next = (node*)malloc(sizeof(node*));
        dugum2->data = i;
        dugum2 = dugum2->next;
    }
    dugum4 = dugum;
    dogrusıralama(dugum);
    dugum3 = terssıralama(dugum);

    for (int i = 0; i < 6; i++)
    {
        printf("\n");
        printf("%d", dugum3->data);
        dugum3 = dugum3->next;
    }
     
} '