算法題:合並兩個有序的鏈表


說明:本文僅供學習交流,轉載請標明出處,歡迎轉載!

             題目:已知有兩個有序的單鏈表,其頭指針分別為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
 
  1. Node *ListMerge1(Node *head1,Node *head2)//采用遞歸的方法實現  
  2. {  
  3.     if(head1==NULL)  
  4.         return head2;  
  5.     if(head2==NULL)  
  6.         return head1;  
  7.     Node *head=NULL;  
  8.     if(head1->value < head2->value)  
  9.     {  
  10.         head=head1;  
  11.         head->next=ListMerge1(head1->next,head2);  
  12.     }  
  13.     else  
  14.     {  
  15.         head=head2;  
  16.         head->next=ListMerge1(head1,head2->next);  
  17.     }  
  18.     return head;  
  19. }  

 

         算法的非遞歸實現如下:

 

[cpp]  view plain  copy
 
  1. Node *ListMerge(Node *head1,Node *head2)  
  2. {  
  3.     if(!head1) return head2;  
  4.     if(!head2) return head1;  
  5.     Node *head=NULL;//合並后的頭指針  
  6.     Node *p1=head1;//p1用於掃描鏈表1  
  7.     Node *p2=head2;//p2用於掃描鏈表2  
  8.     if(head1->value<head2->value)  
  9.     {  
  10.         head=head1;  
  11.         p1=head1->next;  
  12.     }  
  13.     else  
  14.     {  
  15.         head=head2;  
  16.         p2=head2->next;  
  17.     }  
  18.     Node *p=head;//p永遠指向最新合並的結點  
  19.     while(p1 && p2)//如果循環停止,則p1或p2至少有一個為NULL  
  20.     {  
  21.         if(p1->value<p2->value)  
  22.         {  
  23.             p->next=p1;  
  24.             p1=p1->next;  
  25.         }  
  26.         else  
  27.         {  
  28.             p->next=p2;  
  29.             p2=p2->next;  
  30.         }  
  31.         p=p->next;  
  32.     }  
  33.     if(p1)//如果鏈1還沒走完  
  34.     {  
  35.         p->next=p1;  
  36.     }  
  37.     else if(p2)//如果鏈2還沒走完  
  38.     {  
  39.         p->next=p2;  
  40.     }  
  41.     return head;  
  42. }  

 

          整個測試代碼如下:

 

[cpp]  view plain  copy
 
  1. #include<iostream>  
  2. using namespace std;  
  3. struct Node  
  4. {  
  5.     int value;  
  6.     Node* next;  
  7.     Node(int v):value(v){}  
  8. };  
  9. /*創建一個鏈表,1->2->3->4->5->6->7*/  
  10. Node* CreateList1()//創建一個有序的單鏈表1  
  11. {  
  12.    Node *head;  
  13.    Node *n1=new Node(1);  
  14.    Node *n3=new Node(3);  
  15.    Node *n5=new Node(5);  
  16.    Node *n7=new Node(7);  
  17.    Node *n9=new Node(9);  
  18.    head=n1;  
  19.    n1->next=n3;  
  20.    n3->next=n5;  
  21.    n5->next=n7;  
  22.    n7->next=n9;  
  23.    n9->next=NULL;  
  24.    return head;  
  25. }  
  26. Node* CreateList2()//創建一個有序的單鏈表2  
  27. {  
  28.    Node *head;  
  29.    Node *n2=new Node(2);  
  30.    Node *n4=new Node(4);  
  31.    Node *n6=new Node(6);  
  32.    Node *n8=new Node(8);  
  33.    head=n2;  
  34.    n2->next=n4;  
  35.    n4->next=n6;  
  36.    n6->next=n8;  
  37.    n8->next=NULL;  
  38.    return head;  
  39. }  
  40. void FreeList(Node *head)//將鏈表空間釋放  
  41. {  
  42.     if(head==NULL)  
  43.     {  
  44.         return ;  
  45.     }  
  46.     else  
  47.     {  
  48.         Node *temp=head->next;  
  49.         delete head;  
  50.         head=temp;  
  51.         FreeList(head);  
  52.     }  
  53. }  
  54.   
  55. void VisitList(Node *head)//遍歷鏈表中的元素,用遞歸的方法遍歷  
  56. {  
  57.     if(head)  
  58.     {  
  59.         cout<<head->value<<"->";  
  60.         VisitList(head->next);  
  61.     }  
  62.     else  
  63.     {  
  64.         cout<<"null"<<endl;  
  65.     }  
  66. }  
  67. Node *ListMerge(Node *head1,Node *head2)  
  68. {  
  69.     if(!head1) return head2;  
  70.     if(!head2) return head1;  
  71.     Node *head=NULL;//合並后的頭指針  
  72.     Node *p1=head1;//p1用於掃描鏈表1  
  73.     Node *p2=head2;//p2用於掃描鏈表2  
  74.     if(head1->value<head2->value)  
  75.     {  
  76.         head=head1;  
  77.         p1=head1->next;  
  78.     }  
  79.     else  
  80.     {  
  81.         head=head2;  
  82.         p2=head2->next;  
  83.     }  
  84.     Node *p=head;//p永遠指向最新合並的結點  
  85.     while(p1 && p2)//如果循環停止,則p1或p2至少有一個為NULL  
  86.     {  
  87.         if(p1->value<p2->value)  
  88.         {  
  89.             p->next=p1;  
  90.             p1=p1->next;  
  91.         }  
  92.         else  
  93.         {  
  94.             p->next=p2;  
  95.             p2=p2->next;  
  96.         }  
  97.         p=p->next;  
  98.     }  
  99.     if(p1)//如果鏈1還沒走完  
  100.     {  
  101.         p->next=p1;  
  102.     }  
  103.     else if(p2)//如果鏈2還沒走完  
  104.     {  
  105.         p->next=p2;  
  106.     }  
  107.     return head;  
  108. }  
  109.   
  110. Node *ListMerge1(Node *head1,Node *head2)//采用遞歸的方法實現  
  111. {  
  112.     if(head1==NULL)  
  113.         return head2;  
  114.     if(head2==NULL)  
  115.         return head1;  
  116.     Node *head=NULL;  
  117.     if(head1->value < head2->value)  
  118.     {  
  119.         head=head1;  
  120.         head->next=ListMerge1(head1->next,head2);  
  121.     }  
  122.     else  
  123.     {  
  124.         head=head2;  
  125.         head->next=ListMerge1(head1,head2->next);  
  126.     }  
  127.     return head;  
  128. }  
  129. int main()  
  130. {  
  131.     Node *head1=CreateList1();  
  132.     Node *head2=CreateList2();  
  133.     cout<<"歸並前"<<endl;  
  134.     cout<<"鏈表1:";  
  135.     VisitList(head1);  
  136.     cout<<"鏈表2:";  
  137.     VisitList(head2);  
  138.     cout<<"合並后的鏈表:";  
  139.     //Node *head=ListMerge(head1,head2);  
  140.     Node *head=ListMerge1(head1,head2);  
  141.     VisitList(head);  
  142.     FreeList(head);  
  143.     return 0;  
  144. }  

 

          測試結果如下:


參考資料-------------《劍指offer》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM