简单来讲,单向链表的反转操作是由n个移除操作和n个插入操作构成(假设单向链表的长度为n)。而迭代法和递归法,分别从两个方向进行“移除”和“插入”。迭代法从前向后将单向链表的元素依次移除,并插入到单向链表的开头;递归法从后向前将单向链表的元素依次移除,并插入到单向链表的最后。
以下见代码:
typedef struct node LinkNode;
struct node {
int data;
LinkNode* next;
};
// 迭代法
void reverseLinkDD(LinkNode** head)
{
if (head == NULL || *head == NULL) return;
LinkNode* first = *head; // 原始的 单链表的第一个结点,即反转后的最后一个结点
LinkNode* ph = first->next;
// 如果反转后的最后一个结点 的后边还存在结点,就将其移除,并将它插入到链表的开头
while (ph != NULL) {
first->next = first->next->next;// 移除结点
// 插入到链表的开头
ph->next = *head;
*head = ph;
ph = first->next;
}
}
// 递归法
LinkNode* reverseLinkDG(LinkNode** ph)
{
// 当前结点(*ph)为未反转的 子单链表 的第一个结点
if (ph == NULL || *ph == NULL) return *ph;// 空链表
if ((*ph)->next == NULL) return *ph;// 当前结点(*ph)只有一个元素,无需反转,返回该结点的指针
LinkNode* first = (*ph)->next;// 分割成更小的 子子单链表,下一个结点为 子子单链表的第一个结点
LinkNode* last = reverseLinkDG(&first);// 求得已经反转的 子子单链表 的最后一个结点的指针
// 将当前结点(*ph) 插入已经反转的 子子单链表 的最后一个结点的后边
(*ph)->next = last->next;
last->next = *ph;
*ph = first;// 令当前结点(*ph)指向已经反转完成的 子单链表 的第一个结点,当前 子单链表 反转成功
return last->next;// 返回当前 子单链表 的最后一个结点的指针
}