前言:
🎈欢迎大家来到Dream_Chaser~的博客🎈
本文收录于 C--数据结构刷题的专栏中 -->http://t.csdn.cn/n6UEP
首先欢迎大家的来访,其次如有错误,非常欢迎大家的指正!我会及时更正错误!
目录
一.合并两个有序链表
来源:21. 合并两个有序链表 - 力扣(LeetCode)
题目:
解析:
函数的参数是两个指向 ListNode 结构体的指针, ListNode 是一个常见的链表节点结构。ListNode 结构一般包含两个成员:一个是存储节点值的变量(比如 val ),另一个是指向下一个节点的指针(比如 next )。
目的是把两个已排序的链表( list1 和 list2 )合并为一个新的已排序的链表,并返回这个新链表的头节点。
1.1核心逻辑
以下是该函数的核心逻辑:
-
首先,如果 list1 或 list2 是空链表(即NULL),函数会直接返回另一个链表。这是因为合并一个空链表和一个非空链表的结果就是那个非空链表。
-
接着,它进入了一个while循环。在这个循环中,只要list1 和list2都不为空,就会比较它们当前节点的值。如果 list1 的当前节点值小于 list2 的当前节点值,就把list1 的当前节点加入到新链表中(先让tail -> next= list1 ,然后tail=tail->next 指向list1),,然后 list1 把向后移动一位,。否则,就把list2的当前节点加入到新链表中(先让tail -> next= list2 ,然后tail=tail->next 指向list2),然后把list2向后移动一位。这样可以保证新链表的节点是按照升序排列的。
-
head和 tail 是两个辅助指针,用来构建新链表。head指向新链表的头节点,tail指向新链表的尾节点。每次添加一个新节点时,都会更新tail指向新加入的节点。
-
当list1或 list2 中有一个被完全遍历(即变为NULL)后,while循环就会结束。此时,如果list1或list2中还有剩余的节点,就把这些节点全部加入到新链表的尾部。这是可以做的,因为这些剩余的节点已经是按照升序排列的,而且它们的所有值都大于新链表中已有节点的值。
-
最后,函数返回新链表的头节点 head
1.2两元素相同时选谁尾插?
我解释一下为什么当list1指向的元素与list2指向的元素大小相等时,用list2尾插:
在两个链表元素相等的情况下,默认选择lsit1作为较大的元素。
当list1和list2指向的元素都是1时,来到了if else 语句,如果条件为真,进入循环,则证明选择list2作为较大元素,反之选择list1为较大元素
结果程序来到了else处,此刻list2小于list1,选择list2尾插,说明list1比list2大
动图解析:(点进去放大看更清晰)
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
if(list1==NULL)
return list2;//若第一个链表为 NULL,直接返回第二个链表
if(list2 ==NULL)
return list1;//若第二个链表为 NULL,直接返回第一个链表
struct ListNode* head=NULL,*tail=NULL;
while(list1 && list2)
{
if(list1->val < list2->val)//比较链表元素谁大,核心是小的先为尾插
{
if(tail==NULL)
{
head= tail= list1;
}
else
{
tail->next=list1;//让新链表的结点与list1指向的元素想链接
tail=tail->next;
}
list1=list1->next;//list1往原始链表后面遍历
}
else
{
if(tail == NULL)
{
head= tail =list2;
}
else
{
tail->next=list2;//让新链表的结点与list2指向的元素想链接
tail=tail->next;
}
list2=list2->next;//list2往原始链表后面遍历
}
}
//若其中一个链表已经遍历到NULL,直接把另一个链表的所有元素原封不动拷贝到新链表
if(list1)
{
tail->next=list1;
}
if(list2)
{
tail->next=list2;
}
return head;
}
代码执行:
本文到此结束,如有错误,随时欢迎大家指正!