歸並排序及幾個常用排序比較


 1 void merge(int arr[], int l, int m,int r)
 2 {
 3     int i = 0, j = 0, k =l;
 4     int n1 = m - l + 1;        //左邊步長
 5     int n2 = r - m;            //右邊步長
 6     std::vector<int> vec_l(&arr[l], &arr[m+1]);
 7     std::vector<int> vec_r(&arr[m+1], &arr[r+1]);
 8     while (i < n1&&j < n2)
 9     {
10         if (vec_l[i] <= vec_r[j])
11         {
12             arr[k] = vec_l[i];
13             i++;
14         }
15         else
16         {
17             arr[k] = vec_r[j];
18             j++;
19         }
20         k++;
21     }
22         while (i<n1)
23         {
24             arr[k]= vec_l[i];
25             i++;
26             k++;
27         }
28 
29         while (j<n2)
30         {
31             arr[k] = vec_r[j];
32             j++;
33             k++;
34         }
35     
36 
37 }
38 
39 void mergeSort(int arr[], int l, int r)
40 {
41     if (l < r)
42     {
43         int m = l + (r - l) / 2;
44 
45         mergeSort(arr, l, m);
46         mergeSort(arr, m + 1, r);
47 
48         merge(arr, l, m, r);
49     }
50 }

再貼張排序的時間與空間復雜度的圖

總結: 

為什么堆排序的時間復雜度理想卻很少被采用:

作者:qinzp
鏈接:https://www.zhihu.com/question/23873747/answer/327295185
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
-------------------------------------------------------------------
堆排序下,數據讀取的開銷變大。在計算機進行運算的時候,數據不一定會從內存讀取出來,而是從一種叫cache的存儲單位讀取。原因是cache相比內存,讀取速度非常快,所以cache會把一部分我們經常讀取的數據暫時儲存起來,以便下一次讀取的時候,可以不必跑到內存去讀,而是直接在cache里面找。
一般認為讀取數據遵從兩個原則:temporal locality,也就是不久前讀取過的一個數據,在之后很可能還會被讀取一遍;另一個叫spatial locality,也就是說讀取一個數據,在它周圍內存地址存儲的數據也很有可能被讀取到。因此,在讀取一個單位的數據(比如1個word)之后,不光單個word會被存入cache,與之內存地址相鄰的幾個word,都會以一個block為單位存入cache中。另外,cache相比內存小得多,當cache滿了之后,會將舊的數據剔除,將新的數據覆蓋上去。
在進行堆排序的過程中,由於我們要比較一個數組前一半和后一半的數字的大小,而當數組比較長的時候,這前一半和后一半的數據相隔比較遠,這就導致了經常在cache里面找不到要讀取的數據,需要從內存中讀出來,而當cache滿了之后,以前讀取的數據又要被剔除。
簡而言之快排和堆排讀取arr[i]這個元素的平均時間是不一樣的。
 
----------------------------------------------------------------------
快速排序最優的情況就是每一次取到的元素都剛好平分整個數組,最優的情況下時間復雜度為:O( nlogn )

  最差的情況就是每一次取到的元素就是數組中最小/最大的,這種情況其實就是冒泡排序了(每一次都排好一個元素的順序),快速排序最差的情況下時間復雜度為:O( n^2 )

     最優的情況下空間復雜度為:O(logn)  ;每一次都平分數組的情況
     最差的情況下空間復雜度為:O( n )      ;退化為冒泡排序的情況(用來存儲哨兵變量的臨時值)
----------------------------------------------------------------------------

快排數據越無序越快(加入隨機化后基本不會退化),平均常數最小,不需要額外空間,不穩定排序。
歸排速度穩定,常數比快排略大,需要額外空間(還有個東西叫多路歸並),穩定排序。(歸並排序需要額外空間記錄子數組的值)

------------------------------------------------------------------------

實際問題中歸並排序並不比快排應用少。快排需要遞歸,就這一點基就可以在許多大數據應用場景把它槍斃了。而歸並排序的scale能力比快排好很多,可以分布式處理,其實很受歡迎的


免責聲明!

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



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