4 合并两个排序的链表

0 引言

题目描述:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。链表结点定义如下。

struct ListNode
{
  int val;
  ListNode* next;    
}

1 抽象问题具体化

举例1:
链表1:1->3->5->7
链表1:2->4->6->8
合并链表:1->2->3->4->5->6->7->8

举例2:
链表1:NULL
链表2:1->2->3->4
合并链表:1->2->3->4

举例3:
链表1:NULL
链表2:NULL
合并链表:NULL

2 具体问题抽象化

(1)定义接口:

ListNode* Merge(ListNode* p, ListNode* q);

(2)操作流程

1)输入两个链表,并定义合并链表头结点,保留当前比较小的链表头结点作为返回结点,合并链表的尾节点指向较小的结点

2)开始循环操作:定义循环结束条件,某个链表活动结点指向了NULL,此时跳出循环,而且合并链表尾节点将等于另一个链表活动结点。

3)循环中的操作:当前活动结点等于两个活动结点中的一个,判断两个活动结点哪个小(或者等于),合并结点尾指针指向大的那个结点,并将另一个结点向前移动一个位置。

4)返回合并链表头结点

(3)流程图

 

 3 demo

 

    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1 == NULL)
            return pHead2;
        if(pHead2 == NULL)
            return pHead1;
        ListNode* r = NULL;
        if(pHead1->val <= pHead2->val)
            r = pHead1;        
        else
            r = pHead2;            
        ListNode* tail = r;  // 合并链表活动尾节点
        while(!(pHead1 == NULL || pHead2 == NULL)){
            ListNode* next;
            if(pHead1->val <= pHead2->val){
                next = pHead1->next;
                tail->next = pHead2;
                pHead1 = next;
                tail = tail -> next;
            }
            else{
                next = pHead2->next;
                tail->next = pHead1;
                pHead2 = next;
                tail = tail -> next;
            }    
        }
        return r;
  }

4 代码优化

(1)分析:上述代码中合并列表的尾结点tail与两个活动结点中的一个相等,导致在延长合并链表时(tail->next = pHead2),出现了断裂,不得不保存next,增加了内存开支。可以通过优化代码避免这一点。写法如下。

ListNode* Merge(ListNode* pHead1, ListNode* pHead2){       
     if(pHead1 == NULL)
            return pHead2;
        if(pHead2 == NULL)
            return pHead1;
        ListNode* r = NULL;
        if(pHead1->val <= pHead2->val){
            r = pHead1;
            pHead1 = pHead1->next; // 改动1
        }                    
        else{
            r = pHead2;
            pHead2 = pHead2->next;  // 改动2
        }                        
        ListNode* tail = r;  // 合并链表活动尾节点
        while(!(pHead1 == NULL || pHead2 == NULL)){
       // ListNode* next; // 改动3
if(pHead1->val <= pHead2->val){ tail->next = pHead1; pHead1 = pHead1->next; // 改动4 tail = tail -> next; } else{ tail->next = pHead2; pHead2 = pHead2->next; // 改动5 tail = tail -> next; } } tail ->next = pHead1?pHead1:pHead2; // 改动6 return r; }

 

posted @ 2018-11-17 21:59  十步一杀2017  阅读(159)  评论(0编辑  收藏  举报