单链表---合并两个链表

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

cpp 复制代码
struct ListNode 
{
    int val;
    struct ListNode* next;
};

w

方法一---不使用哨兵位

我们创建一个新链表用于合并两个升序链表, 将两个链表中最小的结点依次尾插到新链表newlist中,当循环结束后,如果list1不为空说明list2为空使循环停止,那么我们将新链表尾插指针cur指向list1,反之指向list2:

cpp 复制代码
    while (list1 && list2)
    {
        if (list1->val < list2->val)
        {
            if (newlist == NULL)
            {
                newlist = cur = list1;
            }
            else
            {
                cur->next = list1;
                cur = cur->next;
            }
            list1 = list1->next;
        }
        else
        {
            if (newlist == NULL)
            {
                newlist = cur = list2;
            }
            else
            {
                cur->next = list2;
                cur = cur->next;
            }
            list2 = list2->next;
        }
    }
    if (list1)
    {
        cur->next = list1;
    }
    if (list2)
    {
        cur->next = list2;
    }
    return newlist;

但是只有这个循环还不行,如果list1与list2开始就为NULL,那么最后cur->next会形成非法访问,因此在代码开始需要进行判断,list1为空则返回list2,list2为空返回list1。

cpp 复制代码
    if (list1 == NULL)
        return list2;
    if (list2 == NULL)
        return list1;

整体代码如下:

cpp 复制代码
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    struct ListNode* newlist, * cur;
    newlist = cur = NULL;
    if (list1 == NULL)
        return list2;
    if (list2 == NULL)
        return list1;
    while (list1 && list2)
    {
        if (list1->val < list2->val)
        {
            if (newlist == NULL)
            {
                newlist = cur = list1;
            }
            else
            {
                cur->next = list1;
                cur = cur->next;
            }
            list1 = list1->next;
        }
        else
        {
            if (newlist == NULL)
            {
                newlist = cur = list2;
            }
            else
            {
                cur->next = list2;
                cur = cur->next;
            }
            list2 = list2->next;
        }
    }
    if (list1)
    {
        cur->next = list1;
    }
    if (list2)
    {
        cur->next = list2;
    }
    return newlist;
}

方法二---使用哨兵位

cpp 复制代码
    newlist = (struct ListNode*)malloc(sizeof(struct ListNode));
    cur = newlist;

使用哨兵位的好处在于,循环内部不需要判断有效结点为空的情况,因为哨兵位不是有效结点,哨兵位的next指向第一个有效结点,因此不用担心有效结点为空导致非法访问。

cpp 复制代码
    while(list1&&list2)
    {
        if(list1->val < list2->val)
        {
            cur->next = list1;
            cur=cur->next;
            list1=list1->next;
        }
        else
        {
            cur->next = list2;
            cur=cur->next;
            list2=list2->next;
        }
    }

使用哨兵位的缺陷在于,开辟了额外的空间,在返回之前或者函数结束之前需要释放哨兵位空间并将指向哨兵位的指针置空。

cpp 复制代码
    struct ListNode* tmp = newlist->next;
    free(newlist);
    newlist = NULL;
    return tmp;

那么总体代码如下:

cpp 复制代码
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{
    struct ListNode* newlist ,*cur;
    newlist = (struct ListNode*)malloc(sizeof(struct ListNode));
    cur = newlist;
    if(list1==NULL)
        return list2;
    if(list2==NULL)
        return list1;
    while(list1&&list2)
    {
        if(list1->val < list2->val)
        {
            cur->next = list1;
            cur=cur->next;
            list1=list1->next;
        }
        else
        {
            cur->next = list2;
            cur=cur->next;
            list2=list2->next;
        }
    }
    if(list1)
    {
        cur->next = list1;
    }
    if(list2)
    {
        cur->next = list2;
    }
    struct ListNode* tmp = newlist->next;
    free(newlist);
    newlist = NULL;
    return tmp;
}
相关推荐
余厌厌厌1 分钟前
go语言学习 第9章:映射(Map)
服务器·学习·golang
委婉待续2 分钟前
Qt的学习(一)
开发语言·qt·学习
哆啦A梦的口袋呀39 分钟前
基于Python学习《Head First设计模式》第七章 适配器和外观模式
python·学习·设计模式
笑鸿的学习笔记39 分钟前
虚幻引擎5-Unreal Engine笔记之SET节点的输出引脚获取设置后的最新变量值
笔记·ue5·虚幻
恰薯条的屑海鸥42 分钟前
零基础在实践中学习网络安全-皮卡丘靶场(第十期-Over Permission 模块)
学习·安全·web安全·渗透测试·网络安全学习
草莓熊Lotso1 小时前
【数据结构初阶】--算法复杂度的深度解析
c语言·开发语言·数据结构·经验分享·笔记·其他·算法
KyollBM1 小时前
【CF】Day75——CF (Div. 2) B (数学 + 贪心) + CF 882 (Div. 2) C (01Trie | 区间最大异或和)
c语言·c++·算法
东京老树根1 小时前
SAP学习笔记 - 开发27 - 前端Fiori开发 Routing and Navigation(路由和导航)
笔记·学习
CodeOfCC2 小时前
c语言 封装跨平台线程头文件
linux·c语言·windows
Andrew_Xzw2 小时前
数据结构与算法(快速基础C++版)
开发语言·数据结构·c++·python·深度学习·算法