链表(2)反转链表

题目描述

反转一个单链表。(题目来源

思路一

其实,反转一个单向链表,我们可以看成是将链表中的每个结点的指向反向(即从后一个结点指向前一个结点)。

我们在考虑情况的时候,还是可以先考虑一般情况,再考虑特殊情况。

一、一般情况

我们如果直接让后一个结点指向前一个结点,那么后一个结点所指向的再后面的结点的位置就无从知晓了,因此我们定义3个指针变量:n1,n2,n3。

n1:记录指针指向将要反转的结点反转后要指向的结点。

n2:记录指针指向将要反转的结点。

n3:记录指针指向将要反转的下一个结点。

在反转时,首先让n2指向的结点指向n1指向的位置,然后让n1,n2,n3指针统一后移,准备执行下一对结点之间指向的反转。

如此进行下去,所有结点指向都将反转。

二、极端情况

1.传入的链表为空时

若为空,直接返回头指针即可。

若传入链表只有一个结点,同上。

2.反转第一个结点指针的指向

因为在我们反转的过程中就是让n2指向的结点指向n1指向的位置,所以我们只需将n1的初始值赋值为NULL即可。

3.反转最后一个结点指针的指向

此时发现了遍历链表的终止条件和需要返回的新的头指针,即当n2指针为NULL时停止遍历,并且返回n1指针指向的位置。但是,这时这三个指针统一后移时,n3指针的后移将失败,因为n3后移前指向的是NULL,所以不能执行以下这句代码。

n3 = n3 -> next;

所以后移n3指针前需判断其是否为空。

代码实现

struct ListNode {
	int val;
	struct ListNode* next;
};

struct ListNode* reverseList(struct ListNode* head)
{
	if (head == NULL || head->next == NULL)//当链表为空或只有一个结点时,无需操作
		return head;//直接返回

	struct ListNode* n1 = NULL;//记录指针指向将要反转的结点反转后要指向的位置。
	struct ListNode* n2 = head;//记录指针指向将要反转的结点。
	struct ListNode* n3 = head->next;//记录指针指向将要反转的结点的下一个结点。
	while (n2)//n2为NULL时,停止遍历
	{
		n2->next = n1;//反转结点指向
		n1 = n2;//指针后移
		n2 = n3;//指针后移
		if (n3)//判断n3是否为NULL
			n3 = n3->next;//指针后移
	}
	return n1;//返回n1指针指向的位置
}

思路二

将原链表的结点,从头到尾一个个地拿下来头插到一个新链表中,这个新链表起始为一个空链表(newhead指向NULL)。

代码实现

struct ListNode {
	int val;
	struct ListNode* next;
};

struct ListNode* reverseList(struct ListNode* head)
{
	struct ListNode* cur = head;//记录当前待头插的结点
	struct ListNode* newhead = NULL;//新链表初始时为空
	while (cur)//链表中结点头插完毕时停止循环
	{
		struct ListNode* next = cur->next;//记录下一个待头插的结点
		cur->next = newhead;//将结点头插至新链表
		newhead = cur;//新链表头指针后移
		cur = next;//指向下一个待头插的结点
	}
	return newhead;//返回反转后的头指针
}

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值