Kar*_*lra 4 c pointers linked-list
当我说不使用任何指针时,我的意思是我们仍然使用“next”指针字段来遍历列表,但在反转链表时不会更改它们。
据我所知,似乎有办法做到这一点:
如果有人能帮助我了解如何使用第一种方法,我将不胜感激。也欢迎其他方法。
今天在工作中,我不断地回到这个问题试图弄明白它。我发现你的限制有点令人困惑,因此“你试过魔法吗?” 评论。最终我越过了街区......
它可能有助于可视化问题。让我们从 Julio Moreno 的代码中的想法开始,稍微简化:遍历列表并将每个节点数据与尾数据交换。
A B C D E
E B C D A
E A C D B
E A B D C
E A B C D
E D B C A
E D A C B
E D A B C
E D C B A
Run Code Online (Sandbox Code Playgroud)
(在工作中,我得出结论该过程不会成功,但现在我有更多时间可以看到它)。如果我们仔细看看他的函数,我们会发现在此之上,它也递归地工作。我并不热衷于可视化从 for 循环调用的递归函数。这个过程显然不会因为效率而赢得任何奖励。
那么让我们看看如果我们不想限制自己不修改节点位置,我们可以做什么:
A B C D E
B C D E A
C D E B A
D E C B A
E D C B A
Run Code Online (Sandbox Code Playgroud)
这里我们取尾节点E,记住它。我们现在取节点 A 并将其插入 E 之后,然后 B 并在 E 之后但在 A 之前再次插入它,在 E 之后立即插入整个列表,直到 E 是列表的第一个节点(头)。它有效,但我们不允许这样做。
让我们更进一步,假设它是一个双向链表,我们维护两个指针,一个在列表的开头,一个在列表的末尾,我们交换两者的数据,然后增加一个并减少另一个, 分别。
A B C D E
E B C D A
E D C B A
Run Code Online (Sandbox Code Playgroud)
完成了!
那么我们怎么能用单链表做到这一点呢?我们需要知道什么?我们怎样才能在前进的同时倒退呢?
让我们从如何通过遍历整个列表来获取最后一个节点开始。
A B C D E F G H
Run Code Online (Sandbox Code Playgroud)
并交换它们:
H B C D E F G A
Run Code Online (Sandbox Code Playgroud)
然后如果我们记得我们交换了数据的两个节点,我们可以从 B 开始并继续前进,直到 node->next 指向现在保存数据 A 的节点。
B C D E F G
Run Code Online (Sandbox Code Playgroud)
并交换它们:
G C D E F B
F D E C
E D
Run Code Online (Sandbox Code Playgroud)
然而,我仍然对重复单步执行列表的想法感到不舒服——即使在过程的每次迭代中单步执行的范围都会缩小。如果我们有一个 LIFO(后进先出)或其他已知的堆栈怎么办?
A B C D E F G H
B C D E F G H ... A
C D E F G H ... B
D E F G H ... C
E F G H ... D
F G H ... E
G H ... F
H ... G...F...E...D...C...B...A
Run Code Online (Sandbox Code Playgroud)
但这是辅助数据存储,我们不允许这样做,但不难看出如何通过递归函数调用和链表实现 LIFO。那么我们如何通过递归函数调用和链表来向前和向后步进呢?我们不需要额外的参数吗?当我们到达列表的末尾时,我们仍然需要知道它是如何开始的。
A B C D E F G H
A,B ^ return 0
A,C ^ return 0
A,D ^ return 0
A,E ^ swap D E done, return 0
A,F ^ swap C F return D
A,G ^ swap B G return C
A,H ^ swap A H return B
Run Code Online (Sandbox Code Playgroud)
我还没有实际测试过这个来证明它,所以它可能是错误的。我现在去测试一下,如果需要,可以发布代码。希望我不必编辑这篇文章说它不起作用;-)
编辑:可以确认它有效。
static lnode* list_private_reverse(lnode* list, lnode* node)
{
lnode* next = node->next;
if (next)
{
lnode* swap = list_private_reverse(list, next);
if (swap)
{
int c = swap->c;
swap->c = node->c;
node->c = c;
if (swap->next == node || swap->next->next == node)
return 0;
return swap->next;
}
return 0;
}
else
{
int c = node->c;
node->c = list->c;
list->c = c;
}
return list->next;
}
lnode* list_reverse(lnode* list)
{
list_private_reverse(list, list);
return list;
}
Run Code Online (Sandbox Code Playgroud)
list_private_reverse 只调用与列表中的元素一样多的次数。