💓 博客主页:倔强的石头的CSDN主页
📝Gitee主页:倔强的石头的gitee主页
⏩ 文章专栏:数据结构与算法刷题系列(C语言)
目录
一、问题描述
二、解题思路详解
合并两个有序链表的思路
解题的步骤
代码的优化
三、C语言代码实现
一、问题描述
二、解题思路详解
合并两个有序链表的思路
创建一个新的链表,将两个链表的节点元素按大小顺序逐个尾插到新的链表中,最后返回新链表的首节点地址
解题的步骤
- 先对两个链表进行判空,如果任意一个链表为空,直接返回另一个链表首节点地址
- 创建两个指针用来指向新链表的首节点和尾节点,初始都指向NULL
- 再创建两个指针p1 p2用来遍历两个有序链表,初始分别指向两个链表的首节点
- 然后进入while循环,当两个链表都未遍历完成时执行循环,先比较p1 和p2指向的节点的元素大小,将较小的节点插入新链表的尾部
- 插入的过程——先判断新链表是否为空
如果为空,新链表的首尾指针都指向该节点
如果不为空,执行尾插。将新链表尾节点的next指针执行该节点,再将尾指针向后移动
完成一个节点插入后,将该节点所属的链表的遍历指针向后移动- 出循环后,说明两个链表其中有一个先遍历完成了
此时进行判断,哪个指针指向空,就将另一个链表剩余节点挂在新链表尾部- 最后,返回新链表的首节点指针
代码的优化
存在问题——每次插入都要判断链表是否为空
解决办法——创建不存储数据的头结点,让链表不为空
不要忘记使用完成后对动态申请空间释放
最后返回新链表第一个有效节点的地址
三、C语言代码实现
struct ListNode
{ //单链表结构
int val;
struct ListNode* next;
};
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
if (list1 == NULL)//先判断两个链表是否为空
return list2;
if (list2 == NULL)
return list1;
struct ListNode* newhead = (struct ListNode*)malloc(sizeof(struct ListNode));//新链表头节点指针
struct ListNode* newtail = newhead;//新链表尾指针
struct ListNode* p1 = list1;//遍历两个链表的指针
struct ListNode* p2 = list2;
while (p1 && p2)//两个链表都不为空执行循环
{ //哪个链表节点数据小,就将其尾插到新链表
if (p1->val > p2->val)
{
newtail->next = p2;
p2 = p2->next;
}
else
{
newtail->next = p1;
p1 = p1->next;
}
newtail = newtail->next;//新链表尾指针向后移动
}
//一定有一个链表先走到空,出循环后将另一个链表剩余节点尾插到新链表
if (p1 == NULL)
{
newtail->next = p2;
}
if (p2 == NULL)
{
newtail->next = p1;
}
struct ListNode* ret = newhead->next;
free(newhead);
newhead = NULL;
return ret;
}