算法題——單鏈表的歸並排序


題目:單鏈表的歸並排序,返回排序后的鏈表。傳統的歸並都是數組,可以隨機訪問元素,鏈表則需要順序遍歷找中間結點。

 

思路

設置兩個指針,一個步長為1, 一個步長為2,當快指針到達尾結點時,慢指針指向中間結點,時間復雜度為O(N);

平分為左鏈表L1和右鏈表L2,遞歸分裂,直到鏈表為空或者只有一個結點;

將鏈表L2的每個結點插入到鏈表L1中,時間復雜度為O(m+n),m、n分別為兩條鏈表的長度。

 

畫出遞歸樹,可知總的時間復雜度為O(N * lgN)。

 

代碼

合並兩個有序的鏈表:

 1 struct ListNode  2 {  3     int value;  4     ListNode *next;  5     ListNode(int v): value(v), next(NULL)  6  {  7  }  8 };  9 
10 ListNode *mergeSortedList(ListNode *L1, ListNode *L2) 11 { 12     ListNode dummy(-1), *p1 = &dummy, *p2 = L2;  //L1的輔助頭結點dummy,因為可能在頭部插入
13     dummy.next = L1; 14     while(p1->next != NULL && p2 != NULL)  //停止條件,也包括了判斷兩個鏈表是否為空
15  { 16         if(p1->next->value >= p2->value) 17  { 18             L2 = p2->next; 19             p2->next = p1->next; 20             p1->next = p2; 21             p1 = p2; 22             p2 = L2; 23  } 24         else
25  { 26             p1 = p1->next; 27  } 28  } 29     if(p1->next == NULL)    //L2可能還有未處理的結點,直接加在L1尾部即可
30  { 31         p1->next = p2; 32  } 33 
34     return dummy.next; 35 }

 

單鏈表的歸並排序:

 1 ListNode *listMergeSort(ListNode *head)  2 {  3     if(head == NULL || head->next == NULL)   //鏈表為空,或者只有一個結點,直接返回
 4         return head;  5     
 6     ListNode *slow = head, *fast = head;  7     while(fast->next != NULL && fast->next->next != NULL)  8  {  9         fast = fast->next->next; 10         slow = slow->next; 11  } 12 
13     ListNode *leftHead = head, *rightHead = slow->next; 14     slow->next = NULL;      //需要把左半鏈表的尾結點的next賦空值,所以用一個變量來記錄右半鏈表的頭
15 
16     leftHead  = listMergeSort(leftHead); 17     rightHead = listMergeSort(rightHead); 18 
19     return mergeSortedList(leftHead, rightHead); 20 }

 


免責聲明!

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



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