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

题目描述


将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

 

 方法一:

 思路

核心是通过比大小将小的节点取下来尾插。

解题方法

写一个新的链表,创造一个新头节点,因为是尾插所以需要找尾,但是每次找尾时间复杂度会变成n2,所以每次尾插后需要将尾更新。最后如果链表长度不一致再将非空链表取下来连接。

 

 

代码实现 

/**
 * Definition for singly-linked list.
 * 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* head=NULL,*tail=NULL;
     //将头节点取小放入新节点
       if(list1->val<list2->val)
      {
         head=tail=list1;
         list1=list1->next;//链表迭代
      }
       else
      {
         head=tail=list2;
         list2=list2->next;//链表迭代
      }
    //取小的下来尾插
    while(list1 && list2)
    {
       if(list1->val>list2->val)
       {
        tail->next=list2;
        list2=list2->next;
       }
       else
       {
        tail->next=list1;
        list1=list1->next;
       }

       tail=tail->next;
    }

    if(list1)//list1不为空
    {
        tail->next=list1;
    }
    else//list2不为空
    {
        tail->next=list2;
    }

   return head;
}

优化

思路

利用带哨兵卫的方法,开辟新链表的头节点,头节点不存数据。这样做就可以免去第一次比较再插入

解题方法 

开辟一个节点空间赋值给新链表的头节点,不存数据,在链表完成后,将此节点删掉。

 

代码优化 

/**
 * Definition for singly-linked list.
 * 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* head=NULL,*tail=NULL;
    //带哨兵卫的办法
    head=tail=(struct ListNode*)malloc(sizeof(struct ListNode));

    //取小的下来尾插
    while(list1 && list2)
    {
       if(list1->val>list2->val)
       {
        tail->next=list2;
        list2=list2->next;
       }
       else
       {
        tail->next=list1;
        list1=list1->next;
       }

       tail=tail->next;
    }

    if(list1)//list1不为空
    {
        tail->next=list1;
    }
    else//list2不为空
    {
        tail->next=list2;
    }

    struct ListNode* relHead=head->next;//因为要返回头节点所以需要将新链表的头存入
    free(head);

    return relHead;
}

 

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
合并两个有序链表,可以使用递归或迭代的方式实现。下面是使用迭代的方式实现C语言代码: ```c #include <stdio.h> #include <stdlib.h> // 定义链表节点结构体 struct ListNode { int val; struct ListNode *next; }; // 创建链表节点 struct ListNode* createNode(int val) { struct ListNode *newNode = (struct ListNode*)malloc(sizeof(struct ListNode)); newNode->val = val; newNode->next = NULL; return newNode; } // 合并两个有序链表 struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) { // 定义头结点和尾节点 struct ListNode *head = createNode(-1); struct ListNode *tail = head; // 比较两个链表的节点值,将小的节点加入新链表中 while (l1 && l2) { if (l1->val <= l2->val) { tail->next = l1; l1 = l1->next; } else { tail->next = l2; l2 = l2->next; } tail = tail->next; } // 将剩余的节点加入新链表中 if (l1) { tail->next = l1; } else { tail->next = l2; } // 返回新链表的头结点 return head->next; } // 打印链表 void printList(struct ListNode *head) { while (head) { printf("%d ", head->val); head = head->next; } printf("\n"); } int main() { // 创建两个有序链表 struct ListNode *l1 = createNode(1); l1->next = createNode(2); l1->next->next = createNode(4); printf("l1: "); printList(l1); struct ListNode *l2 = createNode(1); l2->next = createNode(3); l2->next->next = createNode(4); printf("l2: "); printList(l2); // 合并两个有序链表 struct ListNode *newList = mergeTwoLists(l1, l2); printf("newList: "); printList(newList); return 0; } ``` 在上面的代码中,我们定义了一个`ListNode`结构体表示链表节点,其中包含一个整数值和一个指向下一个节点的指针。`createNode()`函数用于创建一个新的节点,`mergeTwoLists()`函数用于合并两个有序链表,`printList()`函数用于打印链表的值。 在`mergeTwoLists()`函数中,我们首先创建了一个头结点和一个尾节点,将它们都指向头结点。然后我们比较两个链表的节点值,将小的节点加入新链表中,直到其中一个链表为空。最后我们将剩余的节点加入新链表中,最终返回新链表的头结点。 在`main()`函数中,我们创建了两个有序链表,并打印它们的值。然后调用`mergeTwoLists()`函数将它们合并成一个新的有序链表,并打印新链表的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值