单链表——合并两个有序链表

题目:将两个升序链表(list1、list2)合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有结点组成的。
结构体定义:

typedef struct listNode {
	int val;
	struct listNode* next;
}listNode;

示例:
在这里插入图片描述

思路:
创建一个新链表newHead,并用两个指针(l1、l2)分别遍历两个单链表(list1、list2)。比较val值的大小,val值较小的结点尾插到新链表newHead中。(若val值相同,优先尾插list1中的结点)
代码实现:
定义一个新的链表,这个链表中有两个指针newHead和newTail,分别指向这个链表的头、尾结点。再定义两个指针l1和l2分别用来遍历链表list1和链表list2。

listNode* mergeTwoLists(listNode* list1, listNode* list2)
{
	listNode* newHead = NULL, * newTail = NULL;
	listNode* l1 = list1;
	listNode* l2 = list2;
}

现在我们用循环就来实现遍历链表、尾插这些功能。循环体的内容主要先是比较val的大小。然后进行尾插。

while ()
{
	if (l1->val <= l2->val)
	{

	}
	else
	{

	}
}

尾插先判断新链表是不是为空链表,若是空链表。就直接让指针newHead和newTail都指向要尾插的结点即可。若新链表不为空,则让newTail->next指向新链表并且让newTail指向尾结点即可完成尾插操作。在完成尾插后,要记得让l1或者l2指向下一个结点。

while ()
{
	//l1尾插到新链表中
	if (l1->val <= l2->val)
	{
		//链表为空
		if (newHead == NULL)
		{
			newHead = newTail = l1;
		}
		else//链表不为空
		{
			newTail->next = l1;
			newTail = newTail->next;
		}
		l1 = l1->next;
	}
	else//l2尾插到新链表中
	{
		//链表为空
		if (newHead == NULL)
		{
			newHead = newTail = l2;
		}
		else//链表不为空
		{
			newTail->next = l2;
			newTail = newTail->next;
		}
		l2 = l2->next;
	}
}

现在来思考一下循环结束的条件是什么。经过两个新创建的指针l1、l2的遍历,最后一定是会有一个指针比对方先到达NULL指针。所以这两个指针只要有一个是空指针就退出循环。
当退出循环时。只有两种情况:
1、l1为NULL
2、l2为NULL
若l1指针先到达空指针,那么就说明list1里面的所有结点已经全部尾插到新的链表中。此时只要将l2指向的结点直接尾插到新链表中即可。
若l2指针先到达空指针。同理,这里就不多赘述了。
完成这些步骤后最终返回newHead指针。

listNode* mergeTwoLists(listNode* list1, listNode* list2)
{
	listNode* newHead = NULL, * newTail = NULL;
	listNode* l1 = list1;
	listNode* l2 = list2;

	while (l1 && l2)
	{
		//l1尾插到新链表中
		if (l1->val <= l2->val)
		{
			//链表为空
			if (newHead == NULL)
			{
				newHead = newTail = l1;
			}
			else//链表不为空
			{
				newTail->next = l1;
				newTail = newTail->next;
			}
			l1 = l1->next;
		}
		else//l2尾插到新链表中
		{
			//链表为空
			if (newHead == NULL)
			{
				newHead = newTail = l2;
			}
			else//链表不为空
			{
				newTail->next = l2;
				newTail = newTail->next;
			}
			l2 = l2->next;
		}
	}
	//此时退出循环 只有两种可能,1是l1指向空,2是l2指向空
	if (l1)//l1不为空时,l2一定为空。将newTail->next指向l1即可
	{
		newTail->next = l1;
	}
	if (l2)//l2不为空时,l1一定为空。将newTail->next指向l2即可
	{
		newTail->next = l2;
	}
	return newHead;
}

最后还需要注意的是传入空指针的情况,有三种情况
1、list1为空,list2不为空
2、list1不为空,list2为空
3、同时都为空,返回空指针
第一种情况直接返回list2

if (list1 == NULL)
{
	return list2;
}

第二种情况直接返回list1

if (list1 == NULL)
{
	return list2;
}
if (list2 == NULL)
{
	return list1;
}

第三种情况则不需要写额外的代码经行判断。当list1和list2都为空指针时。执行第一个if语句,返回list2,此时list2是空。所以最终返回空指针
完整代码如下:

listNode* mergeTwoLists(listNode* list1, listNode* list2)
{
	if (list1 == NULL)
	{
		return list2;
	}
	if (list2 == NULL)
	{
		return list1;
	}

	listNode* newHead = NULL, * newTail = NULL;
	listNode* l1 = list1;
	listNode* l2 = list2;

	while (l1 && l2)
	{
		//l1尾插到新链表中
		if (l1->val <= l2->val)
		{
			//链表为空
			if (newHead == NULL)
			{
				newHead = newTail = l1;
			}
			else//链表不为空
			{
				newTail->next = l1;
				newTail = newTail->next;
			}
			l1 = l1->next;
		}
		else//l2尾插到新链表中
		{
			//链表为空
			if (newHead == NULL)
			{
				newHead = newTail = l2;
			}
			else//链表不为空
			{
				newTail->next = l2;
				newTail = newTail->next;
			}
			l2 = l2->next;
		}
	}
	//此时退出循环 只有两种可能,1是l1指向空,2是l2指向空
	if (l1)//l1不为空时,l2一定为空。将newTail->next指向l1即可
	{
		newTail->next = l1;
	}
	if (l2)//l2不为空时,l1一定为空。将newTail->next指向l2即可
	{
		newTail->next = l2;
	}
	return newHead;
}

若这篇文章对你有帮助,请给我一个点赞和收藏。靴靴你!(๑˘︶˘๑)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值