合并两条有序链表

题目:两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的!如下图所示:
这里写图片描述

注意问题

这是一个经常被各公司采用的面试题,最容易犯两种错误:

  • 一是在写代码时没有对合并的过程想清楚,导致合并出来的链表不是想要的结果!
  • 二是代码的鲁棒性存在问题,程序一旦有特殊的链表就会崩溃

合并思路

1、先考虑考虑特殊情况,包括输入空链表,两条链表是同一条链表等等情况需要在一开始就考虑好
2、确定新链表的头结点,谁小就把谁当做头结点
3、使用一个指针来维护尾节点,方便尾部插入元素,每插入一个元素就向后移动
4、谁小就把谁插到尾部,然后继续比较
5、注意其中任何一条链表结束不要忘记另一条还没有结束的链表,要在尾部补上
合并两条有序链表

代码

//合并两个有序链表,合并后依然有序 
pList Merge(pList list1, pList list2)
{
    pList newlist = NULL;
    //tail表示链表的尾部
    pNode tail = NULL;

    //先考虑特殊情况
    if (list1 == list2)
        return NULL;
    if (list1 == NULL)
        return list2;
    if (list2 == NULL)
        return list1;

    //确定头节点
    if (list1->data < list2->data)
    {
        newlist = list1;
        list1 = list1->next;
    }
    else{
        newlist = list2;
        list2 = list2->next;
    }

    //两条链表中找较小的元素尾插
    tail = newlist;
    while ((list1 != NULL) && (list2 != NULL))
    {
        if (list1->data < list2->data){
            tail->next = list1;
            list1 = list1->next;
        }
        else{
            tail->next = list2;
            list2 = list2->next;
        }
        tail = tail->next;
    }
    //能走到这里说明其中一条链表已经结束了
    if (list1 == NULL)
    {
        tail->next = list2;
    }
    else{
        tail->next = list1;
    }
    return newlist;
}

测试代码

void test()
{
    int i = 0;
    pList plist1 = NULL;
    pList plist2 = NULL;
    pList plist3 = NULL;
    InitList(&plist1);
    InitList(&plist2);
    for (i = 0; i <= 10; i++)
    {
        if (i % 2 == 0)
            PushBack(&plist1, i);
        else
        {
            PushBack(&plist2, i);
        }
    }
    PushBack(&plist1, 12);
    PushBack(&plist1, 13);
    PrintList(plist1);
    PrintList(plist2);

    plist3 = Merge(plist1, plist2);
    PrintList(plist3);
}

递归的方式更易理解

其实很容易看出来,只要确定了第一个节点,我们可以把它看成是第一个节点与剩下两条链表的合并结果的合并,这样的话只需要有限次的递归便可以完成这个看似复杂的问题!
这里写图片描述

//递归写法
pNode Merge_R(pList list1, pList list2)
{
    pList newlist = NULL;

    //先考虑特殊情况
    if (list1 == list2)
        return NULL;
    if (list1 == NULL)
        return list2;
    if (list2 == NULL)
        return list1;

    //确定头结点
    if (list1->data < list2->data)
    {
        newlist = list1;
        list1->next = Merge_R(list1->next, list2);
    }
    else
    {
        newlist = list2;
        list2->next = Merge_R(list2->next, list1);
    }
    return newlist;
}

考点

  • 考察分析问题能力,考察指针操作能力,应该透彻分析问题形成清晰的思路,才能够写出正确的代码!
  • 考察代码的鲁棒性,需要考虑到很多特殊操作,尤其是空指针的情况和空链表的情况处理!

猜你喜欢

转载自blog.csdn.net/m0_38032942/article/details/81201069