链表面试题--合并两个有序的链表

问题:合并两个有序的链表,合并后结果任有序
非递归实现:两个指针分别遍历两个链表,然后比较两个指针大小,将小的节点取下放到合并后的新链表中,继续向后移动当前的指针,若两个链表至少有一个表扫描走完,走将对应的另一个表,整体添加合并后的新表中,这样就可以实现链表的合并。
这里写图片描述
方法一:

ListNode* MergeList1(ListNode*l1, ListNode*l2)
{
    if (l1 == NULL)
        return l2;
    if (l2 == NULL)
        return l1;

    ListNode*p1 = l1;//指针p1用来遍历链表l1;
    ListNode*p2 = l2;//指针p1用来遍历链表l2;

    ListNode*newhead = NULL;//表示合并后的头节点

    if (l1->_data < l2->_data)//先取l1的节点,然后链上新节点
    {
        newhead = l1;
        p1 = l1->_next;
    }

    else//表示先取l2的节点
    {
        newhead = l2;
        p2 = l2->_next;
    }

    ListNode*p = newhead;//指针p永远指向合并后最新的节点

    while (p1&&p2)//此时至少有一个链表已经走到尾
    {
        if (p1->_data < p2->_data)
        {
            p->_next = p1;
            p1 = p1->_next;
        }
        else
        {
            p->_next = p2;
            p2 = p2->_next;
        }
        p = p->_next;
    }

    if (p1)//链表l1没走完
    {
        p->_next = p1;
    }
    else if (p2)//链表l2没走完
    {
        p->_next = p2;
    }

    return newhead;
}

方法一的特点是非递归,指针使用要小心,代码比较多,时间复杂度O(max(ll1,l2));
方法二:递归实现:

ListNode*MergeList2(ListNode*l1, ListNode*l2)
{
    if (l1 == NULL)
        return l2;
    if (l2 == NULL)
        return l1;

    ListNode*newhead = NULL;//合并后的头结点
    if (l1->_data < l2->_data)
    {
        newhead = l1;
        newhead->_next = MergeList2(l1->_next, l2->_next);
    }
    else
    {
        newhead = l2;
        newhead->_next = MergeList2(l1->_next, l2->_next);
    }
    return newhead;
}

将l1和l2比较,结果小的链上新节点,知道走到递归终止条件l1为空,或者是l2为空,这样就可以实现链表的合并了;递归实现,主要是找到递归出口,但这种时间和空间复杂度高,尤其是节点比较多,递归的深度很深时,会不断的压栈,有很大的开销。
方法三:list迭代器

bool Compare(int l1, int l2)//升序
{
    return l1 < l2;
}
void Testlist()
{
    list<int> l1, l2;
    l1.push_back(1);
    l1.push_back(3);
    l1.push_back(5);
    l1.push_back(7);

    l2.push_back(2);
    l2.push_back(4);
    l2.push_back(6);
    l2.push_back(8);

    l1.merge(l2, Compare);
    list<int>::iterator it = l1.begin();
    while (it!=l1.end())
    {
        cout << *it << "->";
        ++it;
    }
    cout << endl;
}

通过仿函数比较两个链表的大小,然后调用库里面的merge函数实现合并链表的合并,通过迭代器遍历整个链表。
方法三:主要是对库中list的成员函数要求比较熟悉,同时要掌握迭代器的相关知识。时间复杂度O(1);最高效;
四:完整代码:

struct ListNode
{
    ListNode* _next;
    int _data;

    ListNode(int data)
        :_data(data)
    {}
};
void CleanList(ListNode*head)
{
    ListNode*cur = head;
    if (cur == NULL)
    {
        return;
    }
    while (cur)
    {
        ListNode*tmp = cur->_next;
        delete cur;
        cur = tmp;
        CleanList(cur);
    }
}
void Printlist(ListNode*head)
{
    ListNode *cur = head;
    while (cur)
    {
        cout << cur->_data << "->";
        cur = cur->_next;
    }
    cout << endl;
}
//方法一:非递归实现
ListNode* MergeList1(ListNode*l1, ListNode*l2)
{
    if (l1 == NULL)
        return l2;
    if (l2 == NULL)
        return l1;

    ListNode*p1 = l1;//指针p1用来遍历链表l1;
    ListNode*p2 = l2;//指针p1用来遍历链表l2;

    ListNode*newhead = NULL;//表示合并后的头节点

    if (l1->_data < l2->_data)//先取l1的节点,然后链上新节点
    {
        newhead = l1;
        p1 = l1->_next;
    }

    else//表示先取l2的节点
    {
        newhead = l2;
        p2 = l2->_next;
    }

    ListNode*p = newhead;//指针p永远指向合并后最新的节点

    while (p1&&p2)//此时至少有一个链表已经走到尾
    {
        if (p1->_data < p2->_data)
        {
            p->_next = p1;
            p1 = p1->_next;
        }
        else
        {
            p->_next = p2;
            p2 = p2->_next;
        }
        p = p->_next;
    }

    if (p1)//链表l1没走完
    {
        p->_next = p1;
    }
    else if (p2)//链表l2没走完
    {
        p->_next = p2;
    }

    return newhead;
}

//方法二:递归的实现
ListNode*MergeList2(ListNode*l1, ListNode*l2)
{
    if (l1 == NULL)
        return l2;
    if (l2 == NULL)
        return l1;

    ListNode*newhead = NULL;//合并后的头结点
    if (l1->_data < l2->_data)
    {
        newhead = l1;
        newhead->_next = MergeList2(l1->_next, l2->_next);
    }
    else
    {
        newhead = l2;
        newhead->_next = MergeList2(l1->_next, l2->_next);
    }
    return newhead;
}
//方法三list的迭代器的实现
bool Compare(int l1, int l2)//升序
{
    return l1 < l2;
}
void Testlist()
{
    list<int> l1, l2;
    l1.push_back(1);
    l1.push_back(3);
    l1.push_back(5);
    l1.push_back(7);

    l2.push_back(2);
    l2.push_back(4);
    l2.push_back(6);
    l2.push_back(8);

    l1.merge(l2, Compare);
    list<int>::iterator it = l1.begin();
    while (it!=l1.end())
    {
        cout << *it << "->";
        ++it;
    }
    cout << endl;
}
//创建链表l1.
ListNode* CreateList1()
{
    ListNode*head;
    ListNode*n1 = new ListNode(1);
    ListNode*n3 = new ListNode(3);
    ListNode*n5 = new ListNode(5);
    ListNode*n7 = new ListNode(7);

    head = n1;
    n1->_next = n3;
    n3->_next = n5;
    n5->_next = n7;
    n7->_next = NULL;

    return head;
}
//创建链表l2
ListNode* CreateList2()
{
    ListNode*head;
    ListNode*n2 = new ListNode(2);
    ListNode*n4 = new ListNode(4);
    ListNode*n6 = new ListNode(6);
    ListNode*n8 = new ListNode(8);

    head = n2;
    n2->_next = n4;
    n4->_next = n6;
    n6->_next = n8;
    n8->_next = NULL;

    return head;
}
void TestListNode1()
{
    ListNode*l1 = CreateList1();
    ListNode*l2 = CreateList2();

    cout << "合并前链表l1" << endl;
    Printlist(l1);

    cout << "合并前链表l2" << endl;
    Printlist(l2);

    cout << "非递归的实现" << endl;
    ListNode *newhead = MergeList1(l1, l2);
    Printlist(newhead);

    cout << "递归的实现" << endl;
    ListNode*newhead1 = MergeList2(l1, l2);
    Printlist(newhead1);

    cout << "list迭代器实现" << endl;
    Testlist();

    CleanList(newhead);
    CleanList(newhead1);
}

int main()
{
    TestListNode1();
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值