反转链表

51 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情

1、原题概述

给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。

要求:空间复杂度 O(1) ,时间复杂度 O(n) 。

如当输入链表{1,2,3}时,

经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。

以上转换过程如下图所示:

image.png

2、前插法

遍历链表{1,2,3},使用前插法创建一个新的链表。

image.png

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");
	}
}

image.png

截图看上去跟前插法很像,是因为链表在中间断开,空间复杂度要比扦插法小。