C语言——合并两个有序链表

一、题目简述

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
在这里插入图片描述

二、题目分析

因为两个链表都是有序的,可以效仿数组中合并有序数组的方式。

在这里插入图片描述
在上图中,cur1代表数组a开始的位置;cur2代表数组b始的位置。
将两个位置逐一比较。
如果a[cur1]<b[cur2],那么将a[cur1]的数放到新数组中,cur1++;
如果a[cur1]>=b[cur2],那么将c[cur2]放入新数组中,cur2++;
当一个数组走完时,可能存在另一组数组未走完的情况,再将剩余的数据直接放在后面即可。

那么在链表中,也可以采用类似的方法。将val较小的节点先取下来,再继续取另一个较小的节点尾插。重复上述步骤。
当然也有可能出现链表未走完的情况,这时候直接将剩余节点链接到尾上即可。
有一个链表为空直接返回另一个链表。

三、代码分析

1、建立一个哨兵卫节点
struct ListNode* head=NULL;
struct ListNode* fhead=(struct ListNode*)malloc(sizeof(struct ListNode));//建立哨兵卫节点
fhead->next==NULL;//节点初始化
struct ListNode* tail=fhead;//尾节点

在进入循环之前,肯定要选取一个较小的节点作为头节点。如果有一个链表为NULL,那么就要会出现空指针的解引用,需要对链表进行判断。
那么可以malloc一个新的节点fhead作为哨兵节点,将tail(尾节点)置为fhead,而真正的头则是fhead->next。这样可以更方便一些,当然最后要将fhead释放掉,避免内存泄漏。

2、比较节点
  while(list1&&list2)
  {
     if(list1->val<list2->val)//取较小节点
     {
        tail->next=list1;
        list1=list1->next;
     }
     else
     {
        tail->next=list2;
        list2=list2->next;
     }
     tail=tail->next;//更新尾节点
  }

在这里插入图片描述
与数组类似,比较每一个节点。如果list1节点值较小,取list1的头节点,
进行尾插,list2节点不动,等待下一次的比较;如果list2节点较小,取list2头节点,进行尾插,list1节点不动,等待下一次比较。
每一次尾插完一个节点,tail要进行更新。list1和list2的其中一个要向后走动。
在这里插入图片描述

第一次比较list1节点的val较小,取下进行头插,list1向后走,list2不动。
tail更新。

在这里插入图片描述
第二次比较,val相等,随意取一个节点。图中取list2节点,list向后走,list1不动,tail更新。以此类推。
(如果有一个链表为NULL,显然不会进入循环)

3、链接剩余数据
  if(list1)
  {
    tail->next=list1;//链接list1数据
  }
  else{
    tail->next=list2;//链接list2数据
  }

当有一个链表节点以及全部取下来之后,另外一个链表会有数据残留,是较大的值。
在这里插入图片描述

如上图所示:当list1走完后,list2中剩余较大的数据,此时直接将list2链接到fhead的尾部即可。
if(list1),list1不为空,将list1链接到尾部。
else,list2不为空,将list2链接到尾部。

  head=fhead->next;//真正的头节点
  free(fhead);//释放哨兵卫节点
  return head;

head置为fhead->next,再将fhead释放即可。

四、完整代码

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {

  struct ListNode* head=NULL;
  struct ListNode* fhead=(struct ListNode*)malloc(sizeof(struct ListNode));//哨兵卫节点
  fhead->next==NULL;//初始化
  struct ListNode* tail=fhead;//尾节点
  while(list1&&list2)
  {
     if(list1->val<list2->val)//取较小节点
     {
        tail->next=list1;//链接到尾部
        list1=list1->next;
     }
     else
     {
        tail->next=list2;//链接到尾部
        list2=list2->next;
     }
     tail=tail->next;//更新尾节点
  }
  if(list1)//list1不为空
  {
    tail->next=list1;//链接list1数据
  }
  else   //list2不为空
  {  
    tail->next=list2;//链接list2数据
  }
  head=fhead->next;//真正的头节点
  free(fhead);//释放哨兵卫节点
  return head;
}
  • 46
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值