链表OJ4——删除链表中等于给定值 val 的所有节点(c语言实现)

声明:我的链表OJ系列是针对无头单向不循环链表的题目

题目

 力扣OJ链接:. - 力扣(LeetCode) 

解法

我们来看看这个题目啊,怎么做呢?

有两种解法

三指针法

我们完全可以定义三个指针来进行这个删除操作

假设我们要移除的是2

 这样子就完成了

特殊情况

开头——假设我们删除的是第一个元素

我们很快就能发现头指针是没有next的,而且prev得是二级指针,这就需要进行特殊处理 

我们直接放弃prev这个指针,只保留next和cur这两个指针,并使用头指针

 

末尾 ——假设我们删除的是最后一个元素

我们发现末尾好像可以正常使用 ,所以不需要进行特殊处理

空表

我们可以发现,若传入的链表为空链表(NULL),cur指针的值一开始就为空,而我们遍历的终止条件就是当cur为NULL时停止遍历,所以当传入链表为空时,直接执行到函数末尾,即返回头指针(NULL)。

代码实现

 struct ListNode {
     int val;
     struct ListNode *next;
 };
 
struct ListNode* removeElements(struct ListNode* head, int val)
{
	struct ListNode* prev = NULL;//记录待排查结点的前一个结点位置
	struct ListNode* cur = head;//记录当前正在排查的结点位置
	while (cur != NULL)//当cur为空时,循环停止
	{
		if (cur->val == val)//当前排查的结点是待移除的结点
		{
			struct ListNode* next = cur->next;//记录待排查结点的后一个结点位置
			if (cur == head)//待移除的结点是链表的第一个结点
			{
				head = next;//头指针指向next
				free(cur);//释放第一个结点
				cur = next;//将next指针赋值给cur指针
			}
			else//待移除的结点不是链表的第一个结点
			{
				prev->next = next;//prev指针指向的结点指向next
				free(cur);//将cur指针指向的结点释放掉
				cur = next;//将next指针赋值给cur指针
			}
		}
		else//当前排查的结点不是待移除的结点
		{
			prev = cur;//指针后移
			cur = cur->next;//指针后移
		}
	}
	return head;//返回新的头指针
}

头结点法

我们可能觉得三指针法的代码比较复杂,当我们要移除某一个结点时,还需要判断该结点是否为第一个结点,那么有没有什么办法可以不用进行这一步操作呢?

回答是肯定的。办法就是在传入的链表前面强行加上一个头结点,并让链表原来的头指针指向该头结点,这样我们就不用判断待移除的结点是否为第一个结点了(因为现在第一个结点是头结点)。

在加了头结点后,我们就只需要根据常见情况的逻辑进行代码的编写即可。

但是有一点不能忘记,就是在遍历完链表后要将头结点指向的位置(即第一个结点的位置)赋值给头指针,并将头结点释放掉,最后才能返回头指针。

代码

struct ListNode {
	int val;
	struct ListNode *next;
};
struct ListNode* removeElements(struct ListNode* head, int val)
{
	struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));//申请一个头结点,返回其地址
	guard->next = head;//让头结点指向链表的第一个结点
	struct ListNode* cur = guard->next;//cur指针指向原链表第一个结点
	struct ListNode* prev = guard;//prev指针指向头结点
	while (cur != NULL)//当cur为空时,循环停止
	{
		if (cur->val == val)//当前排查的结点是待移除的结点
		{
			struct ListNode* next = cur->next;//记录待排查结点的后一个结点位置
			prev->next = next;//prev指针指向的结点指向next
			free(cur);//将cur指针指向的结点释放掉
			cur = next;//将next指针赋值给cur指针
		}
		else//当前排查的结点不是待移除的结点
		{
			prev = cur;//指针后移
			cur = cur->next;//指针后移
		}
	}
	head = guard->next;//将头结点指向的位置赋值给头指针,使头指针指向链表第一个结点
	free(guard);//释放头结点
	guard = NULL;//及时置空
	return head;//返回新的头指针
}
  • 14
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值