首页 > 代码库 > 面试题17:合并两个排序的链表

面试题17:合并两个排序的链表

题目描述:

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
(hint: 请务必使用链表。)

输入:

输入可能包含多个测试样例,输入以EOF结束。
对于每个测试案例,输入的第一行为两个整数n和m(0<=n<=1000, 0<=m<=1000):n代表将要输入的第一个链表的元素的个数,m代表将要输入的第二个链表的元素的个数。
下面一行包括n个数t(1<=t<=1000000):代表链表一中的元素。接下来一行包含m个元素,s(1<=t<=1000000)。

输出:

对应每个测试案例,
若有结果,输出相应的链表。否则,输出NULL。

样例输入:
5 2
1 3 5 7 9
2 4
0 0
样例输出:
1 2 3 4 5 7 9
NULL

解题思路:

      本题的解题思路比较简单,一般的数据结构的书上都有,在此就不再赘述。本题的考点不是合并的思路,而是考察应聘者的分析问题的能力(能否形成非常清晰的解题思路,指针操作是否熟练)和应聘者能否写出鲁棒性强的代码。
java代码:
import java.io.IOException;
import java.io.StreamTokenizer;
 
public class Main {
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        StreamTokenizer stin = new StreamTokenizer(System.in);
        int m, n,value;
        while (stin.nextToken() != StreamTokenizer.TT_EOF) {
            m = (int) stin.nval;
            stin.nextToken();
            n = (int) stin.nval;
            if (m == 0 && n==0)
                System.out.println("NULL");
            else {
                ListNode head1 = null;
                ListNode head2 = null;
                ListNode p = null;
                for (int i = 0; i < m; i++) {// 初始化链表
                    stin.nextToken();
                    value = http://www.mamicode.com/(int) stin.nval;>C++代码
#include <stdio.h>
 
using namespace std;
 
class LinkNode{
public:
    int val;
    LinkNode *next;
     
    LinkNode(): val(0), next(NULL) {};  
};
 
LinkNode* RetrieveList(int n){
    int val;
     
    if(n <= 0) return NULL;
     
    LinkNode *head = NULL;
    LinkNode *cur = NULL;
    for(int i = 0; i < n; ++i){
        scanf("%d", &val);
             
        if(head == NULL){
            head = new LinkNode();
            cur = head;
            cur->val = val;
        }
        else{
            cur->next = new LinkNode();
            cur = cur->next;
            cur->val = val;
        }
    }
     
    return head;
}
 
void PrintAndDestroyList(LinkNode* head){
    if(head == NULL){
        printf("NULL\n");
        return;
    }
     
    LinkNode *cur = head;
    while(cur){
        printf("%d", cur->val);
             
        cur = cur->next;
        delete head;
        head = cur; 
         
        if(cur) printf(" ");
    }
     
    printf("\n");
}
 
LinkNode* MergeList(LinkNode* head1, LinkNode* head2){
    LinkNode* head = NULL;
    LinkNode** cur = &head;
    while(head1 && head2){
        if(head1->val <= head2->val){
            *cur = head1;
            head1 = head1->next;
        }
        else{
            *cur = head2;
            head2 = head2->next;
        }
        cur = &((*cur)->next);
    }
     
    if(head1 || head2){
        *cur = head1 ? head1 : head2;
    }
     
    return head;    
}
 
int main(void){
    int n, m;
     
    while(scanf("%d", &n) != EOF){
        scanf("%d", &m);
         
        LinkNode *head1 = RetrieveList(n);
        LinkNode *head2 = RetrieveList(m);
         
        LinkNode* head = MergeList(head1, head2);
         
        PrintAndDestroyList(head);
    }
     
    return 0;
}
C代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
  
typedef struct node
{
    int data;
    struct node *next;
}linkNode;
  
linkNode *initLinkList(linkNode *L)
{
    L = (linkNode *)malloc(sizeof(linkNode)); 
      
    if (NULL == L) 
    {
        return NULL;
    }
      
    L->next = NULL;
      
    return L;
}
  
linkNode *createLinkList(linkNode *L, int n)
{
    linkNode *tail = L;
    linkNode *p = NULL;
      
    while (n--)
    {
        p = (linkNode *)malloc(sizeof(linkNode));
        scanf("%d", &p->data);
        tail->next = p;
        tail = p;
    }
      
    tail->next = NULL;
      
    return L;
}
  
linkNode *mergeLinkList(linkNode *LA, linkNode *LB)
{       
    linkNode *tmp =  LA;
    linkNode *pa = LA->next; 
    linkNode *pb = LB->next;
      
    while (pa!=NULL && pb!=NULL)
    {
        if(pa->data < pb->data)
        {
            tmp->next = pa;
            tmp = pa;
            pa = pa->next;
        }
        else
        {
            tmp->next = pb;
            tmp = pb;
            pb = pb->next;   
        }
    }
      
    tmp->next = pa ? pa : pb; /*tmp直接指向剩余部分*/
      
    return LA;
}
  
void printLinkList(linkNode *L)
{
      
    linkNode *p = L;
      
    while (p->next != NULL)
    {
        if (p != L)
        {
            printf(" ");
        }
          
        p = p->next;
        printf("%d", p->data);
    }
      
    printf("\n");
}
  
void destroyLinkList(linkNode *L) 
{ 
    linkNode *p = L->next;
      
    while ( p != NULL ) 
    { 
        L->next = p->next;
        free(p); 
        p = L->next;
    } 
  
    free(L);
    L = NULL;
}
  
int main(void)
{
    int n, m;
      
    while(scanf("%d%d", &n, &m) != EOF)
    {
        if (m+n == 0)
        {
            printf("NULL\n");
        }
        else
        {
            linkNode *LA = NULL;
            linkNode *LB = NULL;
            LA = initLinkList(LA);
            LB = initLinkList(LB);  
              
            LA = createLinkList(LA, n);
            LB = createLinkList(LB, m);
                  
            LA = mergeLinkList(LA, LB);
            printLinkList(LA);  
            destroyLinkList(LA); /*因为在链接的过程中A指向了B,顺带着把B释放了*/
        }       
    }
      
    return 0;
}

测试用例:

      功能测试:输入两个链表有多个结点,结点值互不相同或存在值相等的多个结点。
      特殊输入测试:两个链表中有一个链表为NULL指针,两个链表中只有一个节点。

体会:

      本人觉得,对于这种题目一定要自己都动手,不要只满足于形成思路,要经常手写代码,常用的代码要做到能够随手拈来,且不存在错误。

面试题17:合并两个排序的链表