o(nlogn)的排序演算法
我們先來看看nlogn比n2快多少?
歸併排序(merge sort)
演算法思想:假定待排序表含有n個記錄,遞迴地將前半部分記錄和後半部分記錄各自歸併,得到排序後的兩部分記錄,然後在使用合併演算法將這兩部分合併在一起。
演算法演示:
基本**如下:
// 合併演算法,將arr[l...mid]和arr[mid+1...r]兩部分進行歸併
template
void __merge(t arr, int l, int mid, int r) else
if (j > r) else
if (aux[i - l] < aux[j - l]) else
}}// 遞迴使用歸併排序,對arr[l...r]的範圍進行排序
template
void __mergesort(t arr, int l, int r)
template
void mergesort(t arr, int n)
那我們在main()中呼叫mergesort(),以及我們之前學習過的排序演算法,這裡就不在演示如何新增**了。前面介紹4種基本排序演算法時,已經清楚介紹了如何新增**,如若忘記請檢視之前的排序基礎文章。好了,我們執行我們的程式,看看執行結果吧,結果如下:
merge sort : 0.012 s
insertion sort : 2.121 s
shell sort : 0.014 s
按照我們之前的慣例,此次執行結果是在處理隨機資料的情況下得出來的,但這次我們將資料規模調整到了50000個隨機資料。我們可以明顯發現在處理大規模隨機資料下歸併排序的效率如此之高。
接著我們來看看在近乎有序的隨機資料的情況下,我們的歸併排序是否能保持這種高效率呢?結果如下:
merge sort : 0.008 s
insertion sort : 0.002 s
shell sort : 0.011 s
從結果中發現,我們的歸併排序仍然能保持高效地處理近乎有序的資料。但我們再回顧一下歸併排序的**,不知有沒有發現我們的**中仍有不足之處?不如我們先看看優化後的**:
// 遞迴使用歸併排序,對arr[l...r]的範圍進行排序
template
void __mergesort(t arr, int l, int r)
int mid = (l + r) / 2;
__mergesort(arr, l, mid);
__mergesort(arr, mid + 1, r);
if (arr[mid] > arr[mid + 1])
__merge(arr, l, mid, r);
當我們待排序的資料較少時,我們可以將排序轉變為插入排序。雖然插入排序是時間複雜度為o(n2)的排序演算法,但在處理小規模資料時其效率還是較高的。此處的插入排序演算法原始碼如下:
template
void __insertionsort(t arr, int l, int r)
arr[j] = e;
}return;
}
還有一處優化就是我們增加了乙個if判斷,為什麼要增加這個判斷呢?因為,我們若要進行合併排序操作都是在arr[mid] > arr[mid + 1]的情況下。如若arr[mid] <= arr[mid + 1]則已說明待排序已經有序了,無需再進行合併排序操作了。
好了讓我們看看優化後的執行結果吧(近乎有序的資料):
merge sort : 0.003 s
insertion sort : 0.001 s
shell sort : 0.006 s
上述歸併排序都是使用遞迴實現自頂向下進行排序,現在我們來看看使用遞迴實現自底向上的歸併排序。
(2-路歸併排序)演算法思想:假定待排序表含有n個記錄,則可以看成是n個有序的子表,每個子表長度為1,然而兩兩歸併,得到「n/2」個長度為2或1的有序表;再兩兩歸併,······如此重複,直到合併成乙個長度為n的有序表為止。
演算法演示:
基本**如下:
template
void mergesortbu(t arr, int n) }}
歸併部分我們採用之前的__merge()。好了,我們在main()中呼叫一下吧,其執行結果如下(隨機資料):
merge sortbu : 0.013 s
高階排序演算法 希爾排序
希爾排序 希爾排序是插入排序的優化版。回憶一下插入排序,假如插入排序執行到一半的時候,這時陣列左邊是已經排好序的,而右邊是還沒有排序的。如果有乙個很小的資料項恰好在右邊的位置,這時所有左邊已排好序的陣列都得往右移,騰出空位讓這個小的資料項插入。希爾排序是在插入演算法的基礎上再次降低交換的次數,以此獲...
高階硬菜 排序演算法高階
下面這一章所講解到演算法將是最精彩和有趣的,涉及到的演算法思路將會在你以後的 中經常使用 講解到的演算法有歸併排序 快速排序 堆排 桶排序。歸併排序 merge sort 是利用歸併的思想實現的排序方法,該演算法採用經典的分治策略 divide and conquer 分治法將問題分 divide ...
高階級排序演算法
希爾排序 void shellsort int array,int len o n n 希爾排序關鍵思想先分組,再分別插入排序 array k temp while gap 1 迴圈條件,當gap 1時,恢復至插入排序 選gap的方式現在仍然是計算機界乙個大問題,目前的選擇都是根據大量工程實踐而來 ...