单链表的逆置
给定单链表1->2->3->4->5
返回被反转后的链表5->4->3->2->1
法一:递归实现
解题思路:
- 使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,记作ret
- 此后,每次函数在返回的过程中,让当前结点的下一个结点的next指针指向当前结点
- 同时让当前结点的next指针指向NULL,从而实现从链表尾部开始的局部反转
- 当递归函数全部出栈后,链表反转完成。
//不带头结点的单链表
Node* reverseList(Node* head)
{
if(head == nullptr || head->next == nullptr)
{
return head;
}
Node* newhead = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return newHead;
}
法二:非递归
解题思路:
- 定义两个指针:pre和cur;pre在前cur在后
- 每次让pre的next指向cur,实现一次局部反转
- 局部反转完成之后,pre和cur同时往前移动一个位置
- 循环上述过程,直至pre到达链表尾部
//不带头结点的单链表
Node* reverseList(Node* head)
{
if(head == nullptr || head->next == nullptr)
{
return head;
}
Node* cur = nullptr;
Node* pre = nullptr;
while(head != nullptr)
{
head = head->next;
cur = head;
cur->next = pre;
pre = cur;
}
return cur;
}
法三:利用数组模拟栈
解题思路:
- 先计算有几个结点,再动态开辟一个数组
- 从头到尾遍历链表,将数据全部存放到数组中
- 将数组中的数据从后往前,再赋值到链表中
- 最后释放数组
void Recerse(Node* plist)
{
int len = GetLength(plist);
int *arr = (int*)malloc(sizeof(int)*len);
assert(arr != NULL);
int i = 0;
for(Node* p = plist->next; p != NULL; p = p->next)
{
arr[i++] = p->data;
}
i = len-1;
for(Node* p = plist->next; p != NULL;p = p->next)
{
p->data = arr[i--];
}
free(arr);
}