题目
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
方法一
将单链表储存为数组,然后按照数组的索引逆序进行反转。
浪费空间
方法二
使用3个指针遍历单链表,逐个链接点进行反转。
p = head;
q = head->next;
head->next = NULL;
现在进入循环体,这是第一次循环。
r = q->next;
q->next = p;
p = q;
q =r;
第二次循环。
r = q->next;
q->next = p;
p = q;
q = r;
第三次循环。。。。。
struct ListNode* reverseList(struct ListNode* head) {
if(head==NULL||head->next==NULL) 少于两个节点没有反转的必要
return head;
struct ListNode* p,* q,* r;
p=head;
q=head->next;
head->next=NULL; //旧的头指针是新的尾指针,next需要指向NULL
while(q)
{
r=q->next;
q->next=p;
p=q;
q=r;
}
head=p; // 最后q必然指向NULL,所以返回了p作为新的头指针
return head;
}
方法三
首先将链表断成前半部分和后半部分,前半部分初始时为只有头结点的空链表,后半部分分为不带头结点的原链表。然后依次取后半部分链表中的每个结点,将其作为第一个结点插入到前半部分,使得前半部分多一个结点,后半部分少一个结点,直到后半部分中的结点依次全部被取完为止。
struct ListNode* reverseList(struct ListNode* head) {
if(head==NULL||head->next==NULL)
return head;
struct ListNode* s,* p;
p=head->next;
head->next=NULL;
while(p)
{
s=p;
p=p->next;
s->next=head;
head=s;
}
return head;
}
方法四
我们使用递归的原理是每次调用函数让他的头指针向后走,直到走到尾节点,我们将尾节点作为头,然后递归回去相当于我们倒着访问了这个单链表,具体的过程我们画成了一幅图,图如下奉上。(鼠标点击图片可以放大哦)
struct ListNode* reverseList(struct ListNode* head)
{
if(head == NULL || head -> next == NULL) return head;
struct ListNode* h = reverseList(head -> next);
head -> next -> next = head;
head -> next = NULL;
return h;
}
参考链接:
https://blog.csdn.net/feliciafay/article/details/6841115
https://blog.csdn.net/lucky52529/article/details/84672526