持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情
1、原题概述
给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
要求:空间复杂度 O(1) ,时间复杂度 O(n) 。
如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
以上转换过程如下图所示:
2、前插法
遍历链表{1,2,3},使用前插法创建一个新的链表。
struct ListNode* ReverseList(struct ListNode* pHead ) {
if (pHead == NULL) {
return pHead;
}
struct ListNode* p, *L; //前插法
L = (struct ListNode*)malloc(sizeof(struct ListNode));
L->next = NULL;//创建一个带头结点的空链表
while (pHead != NULL) {
p = (struct ListNode*)malloc(sizeof(struct ListNode));//生成新结点p
p->val = pHead->val;//给元素赋值
p->next=L->next;
L->next=p;//将新节点插入到头结点之后
//printf("%d ",p->val);
pHead = pHead->next;
}
return L->next;//返回不带头的链表
}
3、方法二
struct ListNode* ReverseList(struct ListNode* pHead ) {
struct ListNode *cur,*pre,*q;
cur=NULL;
pre=NULL;
q=pHead;//把头结点赋值给p
while(q!=NULL)//知道q==NULL整个链表反转完毕。
{
cur=pre;//cur向后移动
pre=q;//pre向后移动
q=q->next;//向后移动
pre->next=cur;//pre指针方向反转
}
return pre;//此时p==NULL,pre为首元节点。
}
4、测试分析
#include "stdio.h"
#include "stdlib.h"
typedef int DataType;
typedef struct node
{
DataType num;
struct node *next;
}Node, *list;
list Creat_H()
{
list l;
list p;
l = (struct node *)malloc(sizeof(struct node));
l->next = NULL;
list r;
r = l;
int s = 0;
scanf_s("%d", &s);
while (s != 0) {
p = (struct node *)malloc(sizeof(struct node));
p->num = s;
p->next = NULL; r->next = p; r = p;
scanf_s("%d", &s);
}
return l;
}
void Print(list l)
{
list head = l;
while (head != NULL)
{
printf("%d ", head->num);
head = head->next;
}
}
int main()
{
list l;
printf("单链表初始化赋值,输入0结束:\n");
l = Creat_H();
list cur, pre, q;
cur = NULL;
pre = NULL;
q = l->next;
while (q != NULL)
{
cur = pre;
pre = q;
q = q->next;
pre->next = cur;
printf("pre:");
Print(pre);
printf(" q:");
Print(q);
printf("\n");
}
}
截图看上去跟前插法很像,是因为链表在中间断开,空间复杂度要比扦插法小。