演算法學習,演算法學習網站
歸併排序
歸併排序我在之前已經講過了,並且給了在數組的數列的情況下的歸併排序方法,而排序的時間複雜度為O(NlogN).想看的話連結如下:
歸併排序,快排,冒泡排序
但是這個歸併排序有一個缺點:需要O(n)的額外空間。
那麼這個缺點在什麼情況下會解決呢?就是數列是以鏈表形式儲存的時候!就不需要額外的申請O(n)層級的空間。
那麼我們為什麼要用歸併排序呢? 不是還有快排,堆排嗎?都是速度很快的排序。其實在鏈表中是不適合的!因為在快排的時候,尋找標杆是O(1)層級的,但是在鏈表中只能得到head節點,得到標杆需要O(n)層級的。那麼複雜度就上升到(nnlogn)層級的了。
代碼實現
所以在鏈表的情況下需要使用歸併排序,複雜度NlogN, 而且不需要申請額外空間。
//// main.cpp// MergeList//// Created by Alps on 14/12/6.// Copyright (c) 2014年 chen. All rights reserved.//#include <iostream>using namespace std;struct ListNode{ int val; ListNode* next; ListNode(int x):val(x),next(NULL){}};class Solution{public: ListNode *sortList(ListNode* head){ if (head == NULL || head->next == NULL) { return head; } ListNode* mid = getMid(head); ListNode* right = NULL; if (mid != NULL) { right = mid->next; mid->next = NULL; } head = sortList(head); right = sortList(right); head = MergeList(head, right); return head; } ListNode* getMid(ListNode* node){ if (node == NULL || node->next == NULL) { return node; } ListNode* l1 = node; ListNode* l2 = node->next; while (l2 && l2->next) { l1 = l1->next; l2 = l2->next->next; } return l1; } ListNode* MergeList(ListNode* left, ListNode* right){ if (left == NULL) { return right; } if (right == NULL) { return left; } ListNode* temp = NULL; if (left->val >= right->val) { temp = right->next; right->next = left; left = right; right = temp; } left->next = MergeList(left->next, right); return left; }};int main(int argc, const char * argv[]) { Solution sl; ListNode *head = new ListNode(4); head->next = new ListNode(2); head->next->next = new ListNode(1); head->next->next->next = new ListNode(3); sl.sortList(head); return 0;}