链表OJ5——合并两个有序链表(C语言实现)

本文介绍了如何使用哨兵节点合并两个已排序的无头单向不循环链表,通过比较节点值并尾插到新链表,简化了边界条件处理,提高代码清晰度。
摘要由CSDN通过智能技术生成

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

题目

题目来源:. - 力扣(LeetCode)

思路

该题的思路比较简单,我们只需创建一个头结点,然后从两个链表的表头开始依次比较传入的两个链表的结点的大小,并将两个链表中较小的结点尾插到新链表的后面即可。

完成一次尾插后,接着比较未尾插的结点,并将较小的结点继续尾插到新链表后面。

 直到最后两个链表的结点都被尾插到新链表的后面

注意两点:

  • 1.在尾插过程中,若某一链表已被遍历完毕,则直接将另一个未遍历完的链表剩下的结点尾插到新链表后面即可。
  • 2.函数返回的时候,不是返回头结点的地址,而是第一个结点的地址,所以我们要返回头结点指向的位置并将头结点释放。 
struct ListNode {
	int val;
	struct ListNode *next;
};

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
	struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
    //申请一个头结点
	struct ListNode* tail = guard;//尾指针
	struct ListNode* cur1 = l1;//记录当前遍历到的l1链表的结点位置
	struct ListNode* cur2 = l2;//记录当前遍历到的l2链表的结点位置
	while (cur1&&cur2)//当l1,l2中有一个链表遍历完毕时便停止
	{
		//取小的结点尾插到新链表后面
		if (cur1->val < cur2->val)
		{
			tail->next = cur1;
			cur1 = cur1->next;
		}
		else
		{
			tail->next = cur2;
			cur2 = cur2->next;
		}
		tail = tail->next;//结点增加,尾指针后移
	}
	//将未遍历完的链表的剩余结点接到新链表后面
	if (cur1)
		tail->next = cur1;
	else
		tail->next = cur2;

	struct ListNode* head = guard->next;//新链表的头指针
	free(guard);//释放头结点
	return head;//返回新链表
}

mergeTwoLists 函数是用于合并两个已排序的链表,并返回一个新的已排序链表的头指针。

这个函数使用了“哨兵节点”或“哑节点”(guard node)来简化链表操作,使得在链表头部插入节点时不需要进行特殊处理。 

 哨兵结点

哨兵节点(或称为哑节点、虚拟节点、guard node)在链表操作中是一个常用的技巧,用于简化链表边界条件的处理。

特别是在处理链表的头部时,使用哨兵节点可以避免对链表为空或只有一个节点的特殊情况做额外的判断。

在 mergeTwoLists 函数中,哨兵节点 guard 的作用主要体现在以下几个方面:

  1. 简化头部插入:由于新链表的头部是通过 guard->next 来访问的,所以在合并过程中,我们不需要担心处理新链表的头部节点。我们可以直接设置 guard->next 为要添加的节点,而不需要检查链表是否为空或进行特殊的头节点处理。

  2. 统一处理逻辑:由于哨兵节点的存在,我们不需要为链表的第一个元素编写特殊的代码。无论链表是否为空,或者是否只有一个元素,我们的合并逻辑都可以统一地应用于 cur1 和 cur2 所指向的节点。

  3. 减少边界条件检查:在合并过程中,我们不需要检查新链表是否为空,因为即使原始链表之一为空,我们仍然可以安全地将另一个链表的剩余部分链接到 guard->next

使用哨兵节点可以使代码更加清晰和简洁,减少出错的可能性。然而,它也带来了一些额外的开销,即需要为哨兵节点分配和释放内存。但在大多数情况下,这种开销是可以接受的,因为它提高了代码的可读性和可维护性。

总结来说,哨兵节点是一个在链表操作中非常有用的工具,它可以帮助我们简化代码,减少边界条件的检查,并使逻辑更加一致和清晰。

  • 19
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值