您的位置:首页 > 其它

算法题:合并两个有序的链表

2016-10-04 00:28 246 查看
说明:本文仅供学习交流,转载请标明出处,欢迎转载!

             题目:已知有两个有序的单链表,其头指针分别为head1和head2,实现将这两个链表合并的函数:

          Node* ListMerge(Node *head1,Node *head2)

       这个算法很像我们排序算法中的归并排序,只能说“很像”,因为思想是一样的,但是这个与归并排序还是有区别的,区别如下:

       1.归并排序是针对有序数组,而这里是有序链表;

       2.归并排序排序的时间复杂度为o(nlogn),而这里的时间复杂度最坏情况下为O(m+n),最好的情况下为O(min{m,n})。

       3.归并排序需要重新申请空间,而这里无需再重新申请空间,只需改变链表结点的指针指向。

       而这里算法的思想跟归并排序是一样的,都是对两个待归并的线性表分别设置1个指针,比较这两个当前指针的大小,将小的结点加入到合并后的线性表中,并向后移动当前指针。若两个线性表中,至少有一个表扫描完,走将对应的另一个表之间整体添加到合并后的线性表中。在这里:链表和数组的区别在于,链表只需要改变当前合并序列尾指针的位置,而数组则要将剩下的值依次复制到归并表的尾部

        算法的递归实现如下:

[cpp] view
plain copy

Node *ListMerge1(Node *head1,Node *head2)//采用递归的方法实现  

{  

    if(head1==NULL)  

        return head2;  

    if(head2==NULL)  

        return head1;  

    Node *head=NULL;  

    if(head1->value < head2->value)  

    {  

        head=head1;  

        head->next=ListMerge1(head1->next,head2);  

    }  

    else  

    {  

        head=head2;  

        head->next=ListMerge1(head1,head2->next);  

    }  

    return head;  

}  

         算法的非递归实现如下:

[cpp] view
plain copy

Node *ListMerge(Node *head1,Node *head2)  

{  

    if(!head1) return head2;  

    if(!head2) return head1;  

    Node *head=NULL;//合并后的头指针  

    Node *p1=head1;//p1用于扫描链表1  

    Node *p2=head2;//p2用于扫描链表2  

    if(head1->value<head2->value)  

    {  

        head=head1;  

        p1=head1->next;  

    }  

    else  

    {  

        head=head2;  

        p2=head2->next;  

    }  

    Node *p=head;//p永远指向最新合并的结点  

    while(p1 && p2)//如果循环停止,则p1或p2至少有一个为NULL  

    {  

        if(p1->value<p2->value)  

        {  

            p->next=p1;  

            p1=p1->next;  

        }  

        else  

        {  

            p->next=p2;  

            p2=p2->next;  

        }  

        p=p->next;  

    }  

    if(p1)//如果链1还没走完  

    {  

        p->next=p1;  

    }  

    else if(p2)//如果链2还没走完  

    {  

        p->next=p2;  

    }  

    return head;  

}  

          整个测试代码如下:

[cpp] view
plain copy

#include<iostream>  

using namespace std;  

struct Node  

{  

    int value;  

    Node* next;  

    Node(int v):value(v){}  

};  

/*创建一个链表,1->2->3->4->5->6->7*/  

Node* CreateList1()//创建一个有序的单链表1  

{  

   Node *head;  

   Node *n1=new Node(1);  

   Node *n3=new Node(3);  

   Node *n5=new Node(5);  

   Node *n7=new Node(7);  

   Node *n9=new Node(9);  

   head=n1;  

   n1->next=n3;  

   n3->next=n5;  

   n5->next=n7;  

   n7->next=n9;  

   n9->next=NULL;  

   return head;  

}  

Node* CreateList2()//创建一个有序的单链表2  

{  

   Node *head;  

   Node *n2=new Node(2);  

   Node *n4=new Node(4);  

   Node *n6=new Node(6);  

   Node *n8=new Node(8);  

   head=n2;  

   n2->next=n4;  

   n4->next=n6;  

   n6->next=n8;  

   n8->next=NULL;  

   return head;  

}  

void FreeList(Node *head)//将链表空间释放  

{  

    if(head==NULL)  

    {  

        return ;  

    }  

    else  

    {  

        Node *temp=head->next;  

        delete head;  

        head=temp;  

        FreeList(head);  

    }  

}  

  

void VisitList(Node *head)//遍历链表中的元素,用递归的方法遍历  

{  

    if(head)  

    {  

        cout<<head->value<<"->";  

        VisitList(head->next);  

    }  

    else  

    {  

        cout<<"null"<<endl;  

    }  

}  

Node *ListMerge(Node *head1,Node *head2)  

{  

    if(!head1) return head2;  

    if(!head2) return head1;  

    Node *head=NULL;//合并后的头指针  

    Node *p1=head1;//p1用于扫描链表1  

    Node *p2=head2;//p2用于扫描链表2  

    if(head1->value<head2->value)  

    {  

        head=head1;  

        p1=head1->next;  

    }  

    else  

    {  

        head=head2;  

        p2=head2->next;  

    }  

    Node *p=head;//p永远指向最新合并的结点  

    while(p1 && p2)//如果循环停止,则p1或p2至少有一个为NULL  

    {  

        if(p1->value<p2->value)  

        {  

            p->next=p1;  

            p1=p1->next;  

        }  

        else  

        {  

            p->next=p2;  

            p2=p2->next;  

        }  

        p=p->next;  

    }  

    if(p1)//如果链1还没走完  

    {  

        p->next=p1;  

    }  

    else if(p2)//如果链2还没走完  

    {  

        p->next=p2;  

    }  

    return head;  

}  

  

Node *ListMerge1(Node *head1,Node *head2)//采用递归的方法实现  

{  

    if(head1==NULL)  

        return head2;  

    if(head2==NULL)  

        return head1;  

    Node *head=NULL;  

    if(head1->value < head2->value)  

    {  

        head=head1;  

        head->next=ListMerge1(head1->next,head2);  

    }  

    else  

    {  

        head=head2;  

        head->next=ListMerge1(head1,head2->next);  

    }  

    return head;  

}  

int main()  

{  

    Node *head1=CreateList1();  

    Node *head2=CreateList2();  

    cout<<"归并前"<<endl;  

    cout<<"链表1:";  

    VisitList(head1);  

    cout<<"链表2:";  

    VisitList(head2);  

    cout<<"合并后的链表:";  

    //Node *head=ListMerge(head1,head2);  

    Node *head=ListMerge1(head1,head2);  

    VisitList(head);  

    FreeList(head);  

    return 0;  

}  

          测试结果如下:






参考资料-------------《剑指offer》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息